diff --git a/src/protocol/parser/mod.rs b/src/protocol/parser/mod.rs index 4fbb63b1ce5e21bd3d0374b153d33d04ea3accdb..56c55fd94a737851d21f329f74ce5a0d88abc887 100644 --- a/src/protocol/parser/mod.rs +++ b/src/protocol/parser/mod.rs @@ -1,1807 +1,203 @@ +mod depth_visitor; +mod symbol_table; +mod type_table; + +use depth_visitor::*; +use symbol_table::SymbolTable; + use crate::protocol::ast::*; use crate::protocol::inputsource::*; use crate::protocol::lexer::*; -use crate::protocol::library; - -// The following indirection is needed due to a bug in the cbindgen tool. -type Unit = (); -type VisitorResult = Result; - -trait Visitor: Sized { - fn visit_protocol_description(&mut self, h: &mut Heap, pd: RootId) -> VisitorResult { - recursive_protocol_description(self, h, pd) - } - fn visit_pragma(&mut self, _h: &mut Heap, _pragma: PragmaId) -> VisitorResult { - Ok(()) - } - fn visit_import(&mut self, _h: &mut Heap, _import: ImportId) -> VisitorResult { - Ok(()) - } - - fn visit_symbol_definition(&mut self, h: &mut Heap, def: DefinitionId) -> VisitorResult { - recursive_symbol_definition(self, h, def) - } - fn visit_component_definition(&mut self, h: &mut Heap, def: ComponentId) -> VisitorResult { - recursive_component_definition(self, h, def) - } - fn visit_composite_definition(&mut self, h: &mut Heap, def: CompositeId) -> VisitorResult { - recursive_composite_definition(self, h, def) - } - fn visit_primitive_definition(&mut self, h: &mut Heap, def: PrimitiveId) -> VisitorResult { - recursive_primitive_definition(self, h, def) - } - fn visit_function_definition(&mut self, h: &mut Heap, def: FunctionId) -> VisitorResult { - recursive_function_definition(self, h, def) - } - - fn visit_variable_declaration(&mut self, h: &mut Heap, decl: VariableId) -> VisitorResult { - recursive_variable_declaration(self, h, decl) - } - fn visit_parameter_declaration(&mut self, _h: &mut Heap, _decl: ParameterId) -> VisitorResult { - Ok(()) - } - fn visit_local_declaration(&mut self, _h: &mut Heap, _decl: LocalId) -> VisitorResult { - Ok(()) - } - - fn visit_statement(&mut self, h: &mut Heap, stmt: StatementId) -> VisitorResult { - recursive_statement(self, h, stmt) - } - fn visit_local_statement(&mut self, h: &mut Heap, stmt: LocalStatementId) -> VisitorResult { - recursive_local_statement(self, h, stmt) - } - fn visit_memory_statement(&mut self, h: &mut Heap, stmt: MemoryStatementId) -> VisitorResult { - recursive_memory_statement(self, h, stmt) - } - fn visit_channel_statement( - &mut self, - _h: &mut Heap, - _stmt: ChannelStatementId, - ) -> VisitorResult { - Ok(()) - } - fn visit_block_statement(&mut self, h: &mut Heap, stmt: BlockStatementId) -> VisitorResult { - recursive_block_statement(self, h, stmt) - } - fn visit_labeled_statement(&mut self, h: &mut Heap, stmt: LabeledStatementId) -> VisitorResult { - recursive_labeled_statement(self, h, stmt) - } - fn visit_skip_statement(&mut self, _h: &mut Heap, _stmt: SkipStatementId) -> VisitorResult { - Ok(()) - } - fn visit_if_statement(&mut self, h: &mut Heap, stmt: IfStatementId) -> VisitorResult { - recursive_if_statement(self, h, stmt) - } - fn visit_while_statement(&mut self, h: &mut Heap, stmt: WhileStatementId) -> VisitorResult { - recursive_while_statement(self, h, stmt) - } - fn visit_break_statement(&mut self, _h: &mut Heap, _stmt: BreakStatementId) -> VisitorResult { - Ok(()) - } - fn visit_continue_statement( - &mut self, - _h: &mut Heap, - _stmt: ContinueStatementId, - ) -> VisitorResult { - Ok(()) - } - fn visit_synchronous_statement( - &mut self, - h: &mut Heap, - stmt: SynchronousStatementId, - ) -> VisitorResult { - recursive_synchronous_statement(self, h, stmt) - } - fn visit_return_statement(&mut self, h: &mut Heap, stmt: ReturnStatementId) -> VisitorResult { - recursive_return_statement(self, h, stmt) - } - fn visit_assert_statement(&mut self, h: &mut Heap, stmt: AssertStatementId) -> VisitorResult { - recursive_assert_statement(self, h, stmt) - } - fn visit_goto_statement(&mut self, _h: &mut Heap, _stmt: GotoStatementId) -> VisitorResult { - Ok(()) - } - fn visit_new_statement(&mut self, h: &mut Heap, stmt: NewStatementId) -> VisitorResult { - recursive_new_statement(self, h, stmt) - } - fn visit_put_statement(&mut self, h: &mut Heap, stmt: PutStatementId) -> VisitorResult { - recursive_put_statement(self, h, stmt) - } - fn visit_expression_statement( - &mut self, - h: &mut Heap, - stmt: ExpressionStatementId, - ) -> VisitorResult { - recursive_expression_statement(self, h, stmt) - } - - fn visit_expression(&mut self, h: &mut Heap, expr: ExpressionId) -> VisitorResult { - recursive_expression(self, h, expr) - } - fn visit_assignment_expression( - &mut self, - h: &mut Heap, - expr: AssignmentExpressionId, - ) -> VisitorResult { - recursive_assignment_expression(self, h, expr) - } - fn visit_conditional_expression( - &mut self, - h: &mut Heap, - expr: ConditionalExpressionId, - ) -> VisitorResult { - recursive_conditional_expression(self, h, expr) - } - fn visit_binary_expression(&mut self, h: &mut Heap, expr: BinaryExpressionId) -> VisitorResult { - recursive_binary_expression(self, h, expr) - } - fn visit_unary_expression(&mut self, h: &mut Heap, expr: UnaryExpressionId) -> VisitorResult { - recursive_unary_expression(self, h, expr) - } - fn visit_indexing_expression( - &mut self, - h: &mut Heap, - expr: IndexingExpressionId, - ) -> VisitorResult { - recursive_indexing_expression(self, h, expr) - } - fn visit_slicing_expression( - &mut self, - h: &mut Heap, - expr: SlicingExpressionId, - ) -> VisitorResult { - recursive_slicing_expression(self, h, expr) - } - fn visit_select_expression(&mut self, h: &mut Heap, expr: SelectExpressionId) -> VisitorResult { - recursive_select_expression(self, h, expr) - } - fn visit_array_expression(&mut self, h: &mut Heap, expr: ArrayExpressionId) -> VisitorResult { - recursive_array_expression(self, h, expr) - } - fn visit_call_expression(&mut self, h: &mut Heap, expr: CallExpressionId) -> VisitorResult { - recursive_call_expression(self, h, expr) - } - fn visit_constant_expression( - &mut self, - _h: &mut Heap, - _expr: ConstantExpressionId, - ) -> VisitorResult { - Ok(()) - } - fn visit_variable_expression( - &mut self, - _h: &mut Heap, - _expr: VariableExpressionId, - ) -> VisitorResult { - Ok(()) - } -} - -// Bubble-up helpers -fn recursive_parameter_as_variable( - this: &mut T, - h: &mut Heap, - param: ParameterId, -) -> VisitorResult { - this.visit_variable_declaration(h, param.upcast()) -} - -fn recursive_local_as_variable( - this: &mut T, - h: &mut Heap, - local: LocalId, -) -> VisitorResult { - this.visit_variable_declaration(h, local.upcast()) -} - -fn recursive_call_expression_as_expression( - this: &mut T, - h: &mut Heap, - call: CallExpressionId, -) -> VisitorResult { - this.visit_expression(h, call.upcast()) -} - -// Recursive procedures -fn recursive_protocol_description( - this: &mut T, - h: &mut Heap, - pd: RootId, -) -> VisitorResult { - for &pragma in h[pd].pragmas.clone().iter() { - this.visit_pragma(h, pragma)?; - } - for &import in h[pd].imports.clone().iter() { - this.visit_import(h, import)?; - } - for &def in h[pd].definitions.clone().iter() { - this.visit_symbol_definition(h, def)?; - } - Ok(()) -} -fn recursive_symbol_definition( - this: &mut T, - h: &mut Heap, - def: DefinitionId, -) -> VisitorResult { - // We clone the definition in case it is modified - match h[def].clone() { - Definition::Component(cdef) => this.visit_component_definition(h, cdef.this()), - Definition::Function(fdef) => this.visit_function_definition(h, fdef.this), - } -} +use std::collections::HashMap; -fn recursive_component_definition( - this: &mut T, - h: &mut Heap, - def: ComponentId, -) -> VisitorResult { - match h[def].clone() { - Component::Composite(cdef) => this.visit_composite_definition(h, cdef.this), - Component::Primitive(pdef) => this.visit_primitive_definition(h, pdef.this), - } +// TODO: @fixme, pub qualifier +pub(crate) struct LexedModule { + pub(crate) source: InputSource, + module_name: Vec, + version: Option, + root_id: RootId, } -fn recursive_composite_definition( - this: &mut T, - h: &mut Heap, - def: CompositeId, -) -> VisitorResult { - for ¶m in h[def].parameters.clone().iter() { - recursive_parameter_as_variable(this, h, param)?; - } - this.visit_statement(h, h[def].body) +pub struct Parser { + pub(crate) heap: Heap, + pub(crate) modules: Vec, + pub(crate) module_lookup: HashMap, usize>, // from (optional) module name to `modules` idx } -fn recursive_primitive_definition( - this: &mut T, - h: &mut Heap, - def: PrimitiveId, -) -> VisitorResult { - for ¶m in h[def].parameters.clone().iter() { - recursive_parameter_as_variable(this, h, param)?; - } - this.visit_statement(h, h[def].body) -} - -fn recursive_function_definition( - this: &mut T, - h: &mut Heap, - def: FunctionId, -) -> VisitorResult { - for ¶m in h[def].parameters.clone().iter() { - recursive_parameter_as_variable(this, h, param)?; - } - this.visit_statement(h, h[def].body) -} - -fn recursive_variable_declaration( - this: &mut T, - h: &mut Heap, - decl: VariableId, -) -> VisitorResult { - match h[decl].clone() { - Variable::Parameter(decl) => this.visit_parameter_declaration(h, decl.this), - Variable::Local(decl) => this.visit_local_declaration(h, decl.this), - } -} - -fn recursive_statement(this: &mut T, h: &mut Heap, stmt: StatementId) -> VisitorResult { - match h[stmt].clone() { - Statement::Block(stmt) => this.visit_block_statement(h, stmt.this), - Statement::Local(stmt) => this.visit_local_statement(h, stmt.this()), - Statement::Skip(stmt) => this.visit_skip_statement(h, stmt.this), - Statement::Labeled(stmt) => this.visit_labeled_statement(h, stmt.this), - Statement::If(stmt) => this.visit_if_statement(h, stmt.this), - Statement::While(stmt) => this.visit_while_statement(h, stmt.this), - Statement::Break(stmt) => this.visit_break_statement(h, stmt.this), - Statement::Continue(stmt) => this.visit_continue_statement(h, stmt.this), - Statement::Synchronous(stmt) => this.visit_synchronous_statement(h, stmt.this), - Statement::Return(stmt) => this.visit_return_statement(h, stmt.this), - Statement::Assert(stmt) => this.visit_assert_statement(h, stmt.this), - Statement::Goto(stmt) => this.visit_goto_statement(h, stmt.this), - Statement::New(stmt) => this.visit_new_statement(h, stmt.this), - Statement::Put(stmt) => this.visit_put_statement(h, stmt.this), - Statement::Expression(stmt) => this.visit_expression_statement(h, stmt.this), - Statement::EndSynchronous(_) | Statement::EndWhile(_) | Statement::EndIf(_) => { - unreachable!() // pseudo-statement +impl Parser { + pub fn new() -> Self { + Parser{ + heap: Heap::new(), + modules: Vec::new(), + module_lookup: HashMap::new() } } -} - -fn recursive_block_statement( - this: &mut T, - h: &mut Heap, - block: BlockStatementId, -) -> VisitorResult { - for &local in h[block].locals.clone().iter() { - recursive_local_as_variable(this, h, local)?; - } - for &stmt in h[block].statements.clone().iter() { - this.visit_statement(h, stmt)?; - } - Ok(()) -} - -fn recursive_local_statement( - this: &mut T, - h: &mut Heap, - stmt: LocalStatementId, -) -> VisitorResult { - match h[stmt].clone() { - LocalStatement::Channel(stmt) => this.visit_channel_statement(h, stmt.this), - LocalStatement::Memory(stmt) => this.visit_memory_statement(h, stmt.this), - } -} - -fn recursive_memory_statement( - this: &mut T, - h: &mut Heap, - stmt: MemoryStatementId, -) -> VisitorResult { - this.visit_expression(h, h[stmt].initial) -} - -fn recursive_labeled_statement( - this: &mut T, - h: &mut Heap, - stmt: LabeledStatementId, -) -> VisitorResult { - this.visit_statement(h, h[stmt].body) -} - -fn recursive_if_statement( - this: &mut T, - h: &mut Heap, - stmt: IfStatementId, -) -> VisitorResult { - this.visit_expression(h, h[stmt].test)?; - this.visit_statement(h, h[stmt].true_body)?; - this.visit_statement(h, h[stmt].false_body) -} - -fn recursive_while_statement( - this: &mut T, - h: &mut Heap, - stmt: WhileStatementId, -) -> VisitorResult { - this.visit_expression(h, h[stmt].test)?; - this.visit_statement(h, h[stmt].body) -} - -fn recursive_synchronous_statement( - this: &mut T, - h: &mut Heap, - stmt: SynchronousStatementId, -) -> VisitorResult { - for ¶m in h[stmt].parameters.clone().iter() { - recursive_parameter_as_variable(this, h, param)?; - } - this.visit_statement(h, h[stmt].body) -} - -fn recursive_return_statement( - this: &mut T, - h: &mut Heap, - stmt: ReturnStatementId, -) -> VisitorResult { - this.visit_expression(h, h[stmt].expression) -} - -fn recursive_assert_statement( - this: &mut T, - h: &mut Heap, - stmt: AssertStatementId, -) -> VisitorResult { - this.visit_expression(h, h[stmt].expression) -} -fn recursive_new_statement( - this: &mut T, - h: &mut Heap, - stmt: NewStatementId, -) -> VisitorResult { - recursive_call_expression_as_expression(this, h, h[stmt].expression) -} - -fn recursive_put_statement( - this: &mut T, - h: &mut Heap, - stmt: PutStatementId, -) -> VisitorResult { - this.visit_expression(h, h[stmt].port)?; - this.visit_expression(h, h[stmt].message) -} - -fn recursive_expression_statement( - this: &mut T, - h: &mut Heap, - stmt: ExpressionStatementId, -) -> VisitorResult { - this.visit_expression(h, h[stmt].expression) -} - -fn recursive_expression( - this: &mut T, - h: &mut Heap, - expr: ExpressionId, -) -> VisitorResult { - match h[expr].clone() { - Expression::Assignment(expr) => this.visit_assignment_expression(h, expr.this), - Expression::Conditional(expr) => this.visit_conditional_expression(h, expr.this), - Expression::Binary(expr) => this.visit_binary_expression(h, expr.this), - Expression::Unary(expr) => this.visit_unary_expression(h, expr.this), - Expression::Indexing(expr) => this.visit_indexing_expression(h, expr.this), - Expression::Slicing(expr) => this.visit_slicing_expression(h, expr.this), - Expression::Select(expr) => this.visit_select_expression(h, expr.this), - Expression::Array(expr) => this.visit_array_expression(h, expr.this), - Expression::Constant(expr) => this.visit_constant_expression(h, expr.this), - Expression::Call(expr) => this.visit_call_expression(h, expr.this), - Expression::Variable(expr) => this.visit_variable_expression(h, expr.this), + // TODO: @fix, temporary implementation to keep code compilable + pub fn new_with_source(source: InputSource) -> Result { + let mut parser = Parser::new(); + parser.feed(source)?; + Ok(parser) } -} -fn recursive_assignment_expression( - this: &mut T, - h: &mut Heap, - expr: AssignmentExpressionId, -) -> VisitorResult { - this.visit_expression(h, h[expr].left)?; - this.visit_expression(h, h[expr].right) -} + pub fn feed(&mut self, mut source: InputSource) -> Result { + // Lex the input source + let mut lex = Lexer::new(&mut source); + let pd = lex.consume_protocol_description(&mut self.heap)?; -fn recursive_conditional_expression( - this: &mut T, - h: &mut Heap, - expr: ConditionalExpressionId, -) -> VisitorResult { - this.visit_expression(h, h[expr].test)?; - this.visit_expression(h, h[expr].true_expression)?; - this.visit_expression(h, h[expr].false_expression) -} + // Seek the module name and version + let root = &self.heap[pd]; + let mut module_name_pos = InputPosition::default(); + let mut module_name = Vec::new(); + let mut module_version_pos = InputPosition::default(); + let mut module_version = None; -fn recursive_binary_expression( - this: &mut T, - h: &mut Heap, - expr: BinaryExpressionId, -) -> VisitorResult { - this.visit_expression(h, h[expr].left)?; - this.visit_expression(h, h[expr].right) -} - -fn recursive_unary_expression( - this: &mut T, - h: &mut Heap, - expr: UnaryExpressionId, -) -> VisitorResult { - this.visit_expression(h, h[expr].expression) -} - -fn recursive_indexing_expression( - this: &mut T, - h: &mut Heap, - expr: IndexingExpressionId, -) -> VisitorResult { - this.visit_expression(h, h[expr].subject)?; - this.visit_expression(h, h[expr].index) -} - -fn recursive_slicing_expression( - this: &mut T, - h: &mut Heap, - expr: SlicingExpressionId, -) -> VisitorResult { - this.visit_expression(h, h[expr].subject)?; - this.visit_expression(h, h[expr].from_index)?; - this.visit_expression(h, h[expr].to_index) -} - -fn recursive_select_expression( - this: &mut T, - h: &mut Heap, - expr: SelectExpressionId, -) -> VisitorResult { - this.visit_expression(h, h[expr].subject) -} - -fn recursive_array_expression( - this: &mut T, - h: &mut Heap, - expr: ArrayExpressionId, -) -> VisitorResult { - for &expr in h[expr].elements.clone().iter() { - this.visit_expression(h, expr)?; - } - Ok(()) -} - -fn recursive_call_expression( - this: &mut T, - h: &mut Heap, - expr: CallExpressionId, -) -> VisitorResult { - for &expr in h[expr].arguments.clone().iter() { - this.visit_expression(h, expr)?; - } - Ok(()) -} - -// ==================== -// Grammar Rules -// ==================== - -struct NestedSynchronousStatements { - illegal: bool, -} - -impl NestedSynchronousStatements { - fn new() -> Self { - NestedSynchronousStatements { illegal: false } - } -} - -impl Visitor for NestedSynchronousStatements { - fn visit_composite_definition(&mut self, h: &mut Heap, def: CompositeId) -> VisitorResult { - assert!(!self.illegal); - self.illegal = true; - recursive_composite_definition(self, h, def)?; - self.illegal = false; - Ok(()) - } - fn visit_function_definition(&mut self, h: &mut Heap, def: FunctionId) -> VisitorResult { - assert!(!self.illegal); - self.illegal = true; - recursive_function_definition(self, h, def)?; - self.illegal = false; - Ok(()) - } - fn visit_synchronous_statement( - &mut self, - h: &mut Heap, - stmt: SynchronousStatementId, - ) -> VisitorResult { - if self.illegal { - return Err(ParseError::new( - h[stmt].position(), - "Illegal nested synchronous statement", - )); - } - self.illegal = true; - recursive_synchronous_statement(self, h, stmt)?; - self.illegal = false; - Ok(()) - } - fn visit_expression(&mut self, _h: &mut Heap, _expr: ExpressionId) -> VisitorResult { - Ok(()) - } -} - -struct ChannelStatementOccurrences { - illegal: bool, -} - -impl ChannelStatementOccurrences { - fn new() -> Self { - ChannelStatementOccurrences { illegal: false } - } -} - -impl Visitor for ChannelStatementOccurrences { - fn visit_primitive_definition(&mut self, h: &mut Heap, def: PrimitiveId) -> VisitorResult { - assert!(!self.illegal); - self.illegal = true; - recursive_primitive_definition(self, h, def)?; - self.illegal = false; - Ok(()) - } - fn visit_function_definition(&mut self, h: &mut Heap, def: FunctionId) -> VisitorResult { - assert!(!self.illegal); - self.illegal = true; - recursive_function_definition(self, h, def)?; - self.illegal = false; - Ok(()) - } - fn visit_channel_statement(&mut self, h: &mut Heap, stmt: ChannelStatementId) -> VisitorResult { - if self.illegal { - return Err(ParseError::new(h[stmt].position(), "Illegal channel delcaration")); - } - Ok(()) - } - fn visit_expression(&mut self, _h: &mut Heap, _expr: ExpressionId) -> VisitorResult { - Ok(()) - } -} - -struct FunctionStatementReturns {} - -impl FunctionStatementReturns { - fn new() -> Self { - FunctionStatementReturns {} - } - fn function_error(&self, position: InputPosition) -> VisitorResult { - Err(ParseError::new(position, "Function definition must return")) - } -} - -impl Visitor for FunctionStatementReturns { - fn visit_component_definition(&mut self, _h: &mut Heap, _def: ComponentId) -> VisitorResult { - Ok(()) - } - fn visit_variable_declaration(&mut self, _h: &mut Heap, _decl: VariableId) -> VisitorResult { - Ok(()) - } - fn visit_block_statement(&mut self, h: &mut Heap, block: BlockStatementId) -> VisitorResult { - let len = h[block].statements.len(); - assert!(len > 0); - self.visit_statement(h, h[block].statements[len - 1]) - } - fn visit_skip_statement(&mut self, h: &mut Heap, stmt: SkipStatementId) -> VisitorResult { - self.function_error(h[stmt].position) - } - fn visit_break_statement(&mut self, h: &mut Heap, stmt: BreakStatementId) -> VisitorResult { - self.function_error(h[stmt].position) - } - fn visit_continue_statement( - &mut self, - h: &mut Heap, - stmt: ContinueStatementId, - ) -> VisitorResult { - self.function_error(h[stmt].position) - } - fn visit_assert_statement(&mut self, h: &mut Heap, stmt: AssertStatementId) -> VisitorResult { - self.function_error(h[stmt].position) - } - fn visit_new_statement(&mut self, h: &mut Heap, stmt: NewStatementId) -> VisitorResult { - self.function_error(h[stmt].position) - } - fn visit_expression_statement( - &mut self, - h: &mut Heap, - stmt: ExpressionStatementId, - ) -> VisitorResult { - self.function_error(h[stmt].position) - } - fn visit_expression(&mut self, _h: &mut Heap, _expr: ExpressionId) -> VisitorResult { - Ok(()) - } -} - -struct ComponentStatementReturnNew { - illegal_new: bool, - illegal_return: bool, -} - -impl ComponentStatementReturnNew { - fn new() -> Self { - ComponentStatementReturnNew { illegal_new: false, illegal_return: false } - } -} - -impl Visitor for ComponentStatementReturnNew { - fn visit_component_definition(&mut self, h: &mut Heap, def: ComponentId) -> VisitorResult { - assert!(!(self.illegal_new || self.illegal_return)); - self.illegal_return = true; - recursive_component_definition(self, h, def)?; - self.illegal_return = false; - Ok(()) - } - fn visit_primitive_definition(&mut self, h: &mut Heap, def: PrimitiveId) -> VisitorResult { - assert!(!self.illegal_new); - self.illegal_new = true; - recursive_primitive_definition(self, h, def)?; - self.illegal_new = false; - Ok(()) - } - fn visit_function_definition(&mut self, h: &mut Heap, def: FunctionId) -> VisitorResult { - assert!(!(self.illegal_new || self.illegal_return)); - self.illegal_new = true; - recursive_function_definition(self, h, def)?; - self.illegal_new = false; - Ok(()) - } - fn visit_variable_declaration(&mut self, _h: &mut Heap, _decl: VariableId) -> VisitorResult { - Ok(()) - } - fn visit_return_statement(&mut self, h: &mut Heap, stmt: ReturnStatementId) -> VisitorResult { - if self.illegal_return { - Err(ParseError::new(h[stmt].position, "Component definition must not return")) - } else { - recursive_return_statement(self, h, stmt) - } - } - fn visit_new_statement(&mut self, h: &mut Heap, stmt: NewStatementId) -> VisitorResult { - if self.illegal_new { - Err(ParseError::new( - h[stmt].position, - "Symbol definition contains illegal new statement", - )) - } else { - recursive_new_statement(self, h, stmt) - } - } - fn visit_expression(&mut self, _h: &mut Heap, _expr: ExpressionId) -> VisitorResult { - Ok(()) - } -} - -struct CheckBuiltinOccurrences { - legal: bool, -} - -impl CheckBuiltinOccurrences { - fn new() -> Self { - CheckBuiltinOccurrences { legal: false } - } -} - -impl Visitor for CheckBuiltinOccurrences { - fn visit_synchronous_statement( - &mut self, - h: &mut Heap, - stmt: SynchronousStatementId, - ) -> VisitorResult { - assert!(!self.legal); - self.legal = true; - recursive_synchronous_statement(self, h, stmt)?; - self.legal = false; - Ok(()) - } - fn visit_call_expression(&mut self, h: &mut Heap, expr: CallExpressionId) -> VisitorResult { - match h[expr].method { - Method::Get | Method::Fires => { - if !self.legal { - return Err(ParseError::new(h[expr].position, "Illegal built-in occurrence")); - } - } - _ => {} - } - recursive_call_expression(self, h, expr) - } -} - -struct BuildSymbolDeclarations { - declarations: Vec, -} - -impl BuildSymbolDeclarations { - fn new() -> Self { - BuildSymbolDeclarations { declarations: Vec::new() } - } - fn checked_add(&mut self, h: &mut Heap, decl: DeclarationId) -> VisitorResult { - for &old in self.declarations.iter() { - let id = h[decl].identifier(); - if h[id] == h[h[old].identifier()] { - return match h[decl].clone() { - Declaration::Defined(defined) => Err(ParseError::new( - h[defined.definition].position(), - format!("Defined symbol clash: {}", h[id]), - )), - Declaration::Imported(imported) => Err(ParseError::new( - h[imported.import].position(), - format!("Imported symbol clash: {}", h[id]), - )), - }; - } - } - self.declarations.push(decl); - Ok(()) - } -} - -impl Visitor for BuildSymbolDeclarations { - fn visit_protocol_description(&mut self, h: &mut Heap, pd: RootId) -> VisitorResult { - recursive_protocol_description(self, h, pd)?; - // Move all collected declarations to the protocol description - h[pd].declarations.append(&mut self.declarations); - Ok(()) - } - fn visit_import(&mut self, h: &mut Heap, import: ImportId) -> VisitorResult { - // println!("DEBUG: Warning (at {}:{}), import actually not yet implemented", file!(), line!()); - let vec = library::get_declarations(h, import)?; - // Destructively iterate over the vector - for decl in vec { - self.checked_add(h, decl)?; - } - Ok(()) - } - fn visit_symbol_definition(&mut self, h: &mut Heap, definition: DefinitionId) -> VisitorResult { - let signature = Signature::from_definition(h, definition); - let decl = h - .alloc_defined_declaration(|this| DefinedDeclaration { this, definition, signature }) - .upcast(); - self.checked_add(h, decl)?; - Ok(()) - } -} - -struct LinkCallExpressions { - pd: Option, - composite: bool, - new_statement: bool, -} + for pragma in &root.pragmas { + match &self.heap[*pragma] { + Pragma::Module(module) => { + if !module_name.is_empty() { + return Err( + ParseError2::new_error(&source, module.position, "Double definition of module name in the same file") + .with_postfixed_info(&source, module_name_pos, "Previous definition was here") + ) + } -impl LinkCallExpressions { - fn new() -> Self { - LinkCallExpressions { pd: None, composite: false, new_statement: false } - } - fn get_declaration( - &self, - h: &Heap, - id: SourceIdentifierId, - ) -> Result { - match h[self.pd.unwrap()].get_declaration(h, id.upcast()) { - Some(id) => Ok(id), - None => Err(ParseError::new(h[id].position, "Unresolved method")), - } - } -} + module_name_pos = module.position.clone(); + module_name = module.value.clone(); + }, + Pragma::Version(version) => { + if module_version.is_some() { + return Err( + ParseError2::new_error(&source, version.position, "Double definition of module version") + .with_postfixed_info(&source, module_version_pos, "Previous definition was here") + ) + } -impl Visitor for LinkCallExpressions { - fn visit_protocol_description(&mut self, h: &mut Heap, pd: RootId) -> VisitorResult { - self.pd = Some(pd); - recursive_protocol_description(self, h, pd)?; - self.pd = None; - Ok(()) - } - fn visit_composite_definition(&mut self, h: &mut Heap, def: CompositeId) -> VisitorResult { - assert!(!self.composite); - self.composite = true; - recursive_composite_definition(self, h, def)?; - self.composite = false; - Ok(()) - } - fn visit_new_statement(&mut self, h: &mut Heap, stmt: NewStatementId) -> VisitorResult { - assert!(self.composite); - assert!(!self.new_statement); - self.new_statement = true; - recursive_new_statement(self, h, stmt)?; - self.new_statement = false; - Ok(()) - } - fn visit_call_expression(&mut self, h: &mut Heap, expr: CallExpressionId) -> VisitorResult { - if let Method::Symbolic(id) = h[expr].method { - let decl = self.get_declaration(h, id)?; - if self.new_statement && h[decl].is_function() { - return Err(ParseError::new(h[id].position, "Illegal call expression")); - } - if !self.new_statement && h[decl].is_component() { - return Err(ParseError::new(h[id].position, "Illegal call expression")); + module_version_pos = version.position.clone(); + module_version = Some(version.version); + }, } - // Set the corresponding declaration of the call - h[expr].declaration = Some(decl); } - // A new statement's call expression may have as arguments function calls - let old = self.new_statement; - self.new_statement = false; - recursive_call_expression(self, h, expr)?; - self.new_statement = old; - Ok(()) - } -} - -struct BuildScope { - scope: Option, -} -impl BuildScope { - fn new() -> Self { - BuildScope { scope: None } - } -} - -impl Visitor for BuildScope { - fn visit_symbol_definition(&mut self, h: &mut Heap, def: DefinitionId) -> VisitorResult { - assert!(self.scope.is_none()); - self.scope = Some(Scope::Definition(def)); - recursive_symbol_definition(self, h, def)?; - self.scope = None; - Ok(()) - } - fn visit_block_statement(&mut self, h: &mut Heap, stmt: BlockStatementId) -> VisitorResult { - assert!(!self.scope.is_none()); - let old = self.scope; - // First store the current scope - h[stmt].parent_scope = self.scope; - // Then move scope down to current block - self.scope = Some(Scope::Block(stmt)); - recursive_block_statement(self, h, stmt)?; - // Move scope back up - self.scope = old; - Ok(()) - } - fn visit_synchronous_statement( - &mut self, - h: &mut Heap, - stmt: SynchronousStatementId, - ) -> VisitorResult { - assert!(!self.scope.is_none()); - let old = self.scope; - // First store the current scope - h[stmt].parent_scope = self.scope; - // Then move scope down to current sync - self.scope = Some(Scope::Synchronous(stmt)); - recursive_synchronous_statement(self, h, stmt)?; - // Move scope back up - self.scope = old; - Ok(()) - } - fn visit_expression(&mut self, _h: &mut Heap, _expr: ExpressionId) -> VisitorResult { - Ok(()) - } -} - -struct ResolveVariables { - scope: Option, -} + // Add module to list of modules and prevent naming conflicts + let cur_module_idx = self.modules.len(); + if let Some(prev_module_idx) = self.module_lookup.get(&module_name) { + // Find `#module` statement in other module again + let prev_module = &self.modules[*prev_module_idx]; + let prev_module_pos = self.heap[prev_module.root_id].pragmas + .iter() + .find_map(|p| { + match &self.heap[*p] { + Pragma::Module(module) => Some(module.position.clone()), + _ => None + } + }) + .unwrap_or(InputPosition::default()); -impl ResolveVariables { - fn new() -> Self { - ResolveVariables { scope: None } - } - fn get_variable(&self, h: &Heap, id: SourceIdentifierId) -> Result { - if let Some(var) = self.find_variable(h, id) { - Ok(var) - } else { - Err(ParseError::new(h[id].position, "Unresolved variable")) - } - } - fn find_variable(&self, h: &Heap, id: SourceIdentifierId) -> Option { - ResolveVariables::find_variable_impl(h, self.scope, id) - } - fn find_variable_impl( - h: &Heap, - scope: Option, - id: SourceIdentifierId, - ) -> Option { - if let Some(scope) = scope { - // The order in which we check for variables is important: - // otherwise, two variables with the same name are shadowed. - if let Some(var) = ResolveVariables::find_variable_impl(h, scope.parent_scope(h), id) { - Some(var) + let module_name_msg = if module_name.is_empty() { + format!("a nameless module") } else { - scope.get_variable(h, id) - } - } else { - None - } - } -} - -impl Visitor for ResolveVariables { - fn visit_symbol_definition(&mut self, h: &mut Heap, def: DefinitionId) -> VisitorResult { - assert!(self.scope.is_none()); - self.scope = Some(Scope::Definition(def)); - recursive_symbol_definition(self, h, def)?; - self.scope = None; - Ok(()) + format!("module '{}'", String::from_utf8_lossy(&module_name)) + }; + + return Err( + ParseError2::new_error(&source, module_name_pos, &format!("Double definition of {} across files", module_name_msg)) + .with_postfixed_info(&prev_module.source, prev_module_pos, "Other definition was here") + ); + } + + self.modules.push(LexedModule{ + source, + module_name: module_name.clone(), + version: module_version, + root_id: pd + }); + self.module_lookup.insert(module_name, cur_module_idx); + Ok(pd) } - fn visit_variable_declaration(&mut self, h: &mut Heap, decl: VariableId) -> VisitorResult { - // This is only called for parameters of definitions and synchronous statements, - // since the local variables of block statements are still empty - // the moment it is traversed. After resolving variables, this - // function is also called for every local variable declaration. - // We want to make sure that the resolved variable is the variable declared itself; - // otherwise, there is some variable defined in the parent scope. This check - // imposes that the order in which find_variable looks is significant! - let id = h[decl].identifier(); - let check_same = self.find_variable(h, id); - if let Some(check_same) = check_same { - if check_same != decl { - return Err(ParseError::new(h[id].position, "Declared variable clash")); + pub fn compile(&mut self) { + // Build module lookup + } + + fn resolve_symbols_and_types(&mut self) -> Result<(), ParseError2> { + // Construct the symbol table to resolve any imports and/or definitions, + // then use the symbol table to actually annotate all of the imports. + // If the type table is constructed correctly then all imports MUST be + // resolvable. + // TODO: Update once namespaced identifiers are implemented + let symbol_table = SymbolTable::new(&self.heap, &self.modules)?; + + // Not pretty, but we need to work around rust's borrowing rules, it is + // totally safe to mutate the contents of an AST element that we are + // not borrowing anywhere else. + // TODO: Maybe directly access heap's members to allow borrowing from + // mutliple members of Heap? Not pretty though... + let mut module_index = 0; + let mut import_index = 0; + loop { + if module_index >= self.modules.len() { + break; } - } - recursive_variable_declaration(self, h, decl) - } - fn visit_memory_statement(&mut self, h: &mut Heap, stmt: MemoryStatementId) -> VisitorResult { - assert!(!self.scope.is_none()); - let var = h[stmt].variable; - let id = h[var].identifier; - // First check whether variable with same identifier is in scope - let check_duplicate = self.find_variable(h, id); - if check_duplicate.is_some() { - return Err(ParseError::new(h[id].position, "Declared variable clash")); - } - // Then check the expression's variables (this should not refer to own variable) - recursive_memory_statement(self, h, stmt)?; - // Finally, we may add the variable to the scope, which is guaranteed to be a block - { - let block = &mut h[self.scope.unwrap().to_block()]; - block.locals.push(var); - } - Ok(()) - } - fn visit_channel_statement(&mut self, h: &mut Heap, stmt: ChannelStatementId) -> VisitorResult { - assert!(!self.scope.is_none()); - // First handle the from variable - { - let var = h[stmt].from; - let id = h[var].identifier; - let check_duplicate = self.find_variable(h, id); - if check_duplicate.is_some() { - return Err(ParseError::new(h[id].position, "Declared variable clash")); - } - let block = &mut h[self.scope.unwrap().to_block()]; - block.locals.push(var); - } - // Then handle the to variable (which may not be the same as the from) - { - let var = h[stmt].to; - let id = h[var].identifier; - let check_duplicate = self.find_variable(h, id); - if check_duplicate.is_some() { - return Err(ParseError::new(h[id].position, "Declared variable clash")); - } - let block = &mut h[self.scope.unwrap().to_block()]; - block.locals.push(var); - } - Ok(()) - } - fn visit_block_statement(&mut self, h: &mut Heap, stmt: BlockStatementId) -> VisitorResult { - assert!(!self.scope.is_none()); - let old = self.scope; - self.scope = Some(Scope::Block(stmt)); - recursive_block_statement(self, h, stmt)?; - self.scope = old; - Ok(()) - } - fn visit_synchronous_statement( - &mut self, - h: &mut Heap, - stmt: SynchronousStatementId, - ) -> VisitorResult { - assert!(!self.scope.is_none()); - let old = self.scope; - self.scope = Some(Scope::Synchronous(stmt)); - recursive_synchronous_statement(self, h, stmt)?; - self.scope = old; - Ok(()) - } - fn visit_variable_expression( - &mut self, - h: &mut Heap, - expr: VariableExpressionId, - ) -> VisitorResult { - let var = self.get_variable(h, h[expr].identifier)?; - h[expr].declaration = Some(var); - Ok(()) - } -} - -struct UniqueStatementId(StatementId); - -struct LinkStatements { - prev: Option, -} - -impl LinkStatements { - fn new() -> Self { - LinkStatements { prev: None } - } -} - -impl Visitor for LinkStatements { - fn visit_symbol_definition(&mut self, h: &mut Heap, def: DefinitionId) -> VisitorResult { - assert!(self.prev.is_none()); - recursive_symbol_definition(self, h, def)?; - // Clear out last statement - self.prev = None; - Ok(()) - } - fn visit_statement(&mut self, h: &mut Heap, stmt: StatementId) -> VisitorResult { - if let Some(UniqueStatementId(prev)) = self.prev.take() { - h[prev].link_next(stmt); - } - recursive_statement(self, h, stmt) - } - fn visit_local_statement(&mut self, _h: &mut Heap, stmt: LocalStatementId) -> VisitorResult { - self.prev = Some(UniqueStatementId(stmt.upcast())); - Ok(()) - } - fn visit_labeled_statement(&mut self, h: &mut Heap, stmt: LabeledStatementId) -> VisitorResult { - recursive_labeled_statement(self, h, stmt) - } - fn visit_skip_statement(&mut self, _h: &mut Heap, stmt: SkipStatementId) -> VisitorResult { - self.prev = Some(UniqueStatementId(stmt.upcast())); - Ok(()) - } - fn visit_if_statement(&mut self, h: &mut Heap, stmt: IfStatementId) -> VisitorResult { - // We allocate a pseudo-statement, which combines both branches into one next statement - let position = h[stmt].position; - let pseudo = - h.alloc_end_if_statement(|this| EndIfStatement { this, position, next: None }).upcast(); - assert!(self.prev.is_none()); - self.visit_statement(h, h[stmt].true_body)?; - if let Some(UniqueStatementId(prev)) = self.prev.take() { - h[prev].link_next(pseudo); - } - assert!(self.prev.is_none()); - self.visit_statement(h, h[stmt].false_body)?; - if let Some(UniqueStatementId(prev)) = self.prev.take() { - h[prev].link_next(pseudo); - } - // Use the pseudo-statement as the statement where to update the next pointer - self.prev = Some(UniqueStatementId(pseudo)); - Ok(()) - } - fn visit_while_statement(&mut self, h: &mut Heap, stmt: WhileStatementId) -> VisitorResult { - // We allocate a pseudo-statement, to which the break statement finds its target - let position = h[stmt].position; - let pseudo = - h.alloc_end_while_statement(|this| EndWhileStatement { this, position, next: None }); - // Update the while's next statement to point to the pseudo-statement - h[stmt].next = Some(pseudo); - assert!(self.prev.is_none()); - self.visit_statement(h, h[stmt].body)?; - // The body's next statement loops back to the while statement itself - // Note: continue statements also loop back to the while statement itself - if let Some(UniqueStatementId(prev)) = std::mem::replace(&mut self.prev, None) { - h[prev].link_next(stmt.upcast()); - } - // Use the while statement as the statement where the next pointer is updated - self.prev = Some(UniqueStatementId(pseudo.upcast())); - Ok(()) - } - fn visit_break_statement(&mut self, _h: &mut Heap, _stmt: BreakStatementId) -> VisitorResult { - Ok(()) - } - fn visit_continue_statement( - &mut self, - _h: &mut Heap, - _stmt: ContinueStatementId, - ) -> VisitorResult { - Ok(()) - } - fn visit_synchronous_statement( - &mut self, - h: &mut Heap, - stmt: SynchronousStatementId, - ) -> VisitorResult { - // Allocate a pseudo-statement, that is added for helping the evaluator to issue a command - // that marks the end of the synchronous block. Every evaluation has to pause at this - // point, only to resume later when the thread is selected as unique thread to continue. - let position = h[stmt].position; - let pseudo = h - .alloc_end_synchronous_statement(|this| EndSynchronousStatement { - this, - position, - next: None, - }) - .upcast(); - assert!(self.prev.is_none()); - self.visit_statement(h, h[stmt].body)?; - // The body's next statement points to the pseudo element - if let Some(UniqueStatementId(prev)) = std::mem::replace(&mut self.prev, None) { - h[prev].link_next(pseudo); - } - // Use the pseudo-statement as the statement where the next pointer is updated - self.prev = Some(UniqueStatementId(pseudo)); - Ok(()) - } - fn visit_return_statement(&mut self, _h: &mut Heap, _stmt: ReturnStatementId) -> VisitorResult { - Ok(()) - } - fn visit_assert_statement(&mut self, _h: &mut Heap, stmt: AssertStatementId) -> VisitorResult { - self.prev = Some(UniqueStatementId(stmt.upcast())); - Ok(()) - } - fn visit_goto_statement(&mut self, _h: &mut Heap, _stmt: GotoStatementId) -> VisitorResult { - Ok(()) - } - fn visit_new_statement(&mut self, _h: &mut Heap, stmt: NewStatementId) -> VisitorResult { - self.prev = Some(UniqueStatementId(stmt.upcast())); - Ok(()) - } - fn visit_put_statement(&mut self, _h: &mut Heap, stmt: PutStatementId) -> VisitorResult { - self.prev = Some(UniqueStatementId(stmt.upcast())); - Ok(()) - } - fn visit_expression_statement( - &mut self, - _h: &mut Heap, - stmt: ExpressionStatementId, - ) -> VisitorResult { - self.prev = Some(UniqueStatementId(stmt.upcast())); - Ok(()) - } - fn visit_expression(&mut self, _h: &mut Heap, _expr: ExpressionId) -> VisitorResult { - Ok(()) - } -} - -struct BuildLabels { - block: Option, - sync_enclosure: Option, -} -impl BuildLabels { - fn new() -> Self { - BuildLabels { block: None, sync_enclosure: None } - } -} - -impl Visitor for BuildLabels { - fn visit_block_statement(&mut self, h: &mut Heap, stmt: BlockStatementId) -> VisitorResult { - assert_eq!(self.block, h[stmt].parent_block(h)); - let old = self.block; - self.block = Some(stmt); - recursive_block_statement(self, h, stmt)?; - self.block = old; - Ok(()) - } - fn visit_labeled_statement(&mut self, h: &mut Heap, stmt: LabeledStatementId) -> VisitorResult { - assert!(!self.block.is_none()); - // Store label in current block (on the fly) - h[self.block.unwrap()].labels.push(stmt); - // Update synchronous scope of label - h[stmt].in_sync = self.sync_enclosure; - recursive_labeled_statement(self, h, stmt) - } - fn visit_while_statement(&mut self, h: &mut Heap, stmt: WhileStatementId) -> VisitorResult { - h[stmt].in_sync = self.sync_enclosure; - recursive_while_statement(self, h, stmt) - } - fn visit_synchronous_statement( - &mut self, - h: &mut Heap, - stmt: SynchronousStatementId, - ) -> VisitorResult { - assert!(self.sync_enclosure.is_none()); - self.sync_enclosure = Some(stmt); - recursive_synchronous_statement(self, h, stmt)?; - self.sync_enclosure = None; - Ok(()) - } - fn visit_expression(&mut self, _h: &mut Heap, _expr: ExpressionId) -> VisitorResult { - Ok(()) - } -} - -struct ResolveLabels { - block: Option, - while_enclosure: Option, - sync_enclosure: Option, -} - -impl ResolveLabels { - fn new() -> Self { - ResolveLabels { block: None, while_enclosure: None, sync_enclosure: None } - } - fn check_duplicate_impl( - h: &Heap, - block: Option, - stmt: LabeledStatementId, - ) -> VisitorResult { - if let Some(block) = block { - // Checking the parent first is important. Otherwise, labels - // overshadow previously defined labels: and this is illegal! - ResolveLabels::check_duplicate_impl(h, h[block].parent_block(h), stmt)?; - // For the current block, check for a duplicate. - for &other_stmt in h[block].labels.iter() { - if other_stmt == stmt { - continue; - } else { - if h[h[other_stmt].label] == h[h[stmt].label] { - return Err(ParseError::new(h[stmt].position, "Duplicate label")); - } + let module_root_id = self.modules[module_index].root_id; + let import_id = { + let root = &self.heap[module_root_id]; + if import_index >= root.imports.len() { + module_index += 1; + import_index = 0; + continue } - } - } - Ok(()) - } - fn check_duplicate(&self, h: &Heap, stmt: LabeledStatementId) -> VisitorResult { - ResolveLabels::check_duplicate_impl(h, self.block, stmt) - } - fn get_target( - &self, - h: &Heap, - id: SourceIdentifierId, - ) -> Result { - if let Some(stmt) = ResolveLabels::find_target(h, self.block, id) { - Ok(stmt) - } else { - Err(ParseError::new(h[id].position, "Unresolved label")) - } - } - fn find_target( - h: &Heap, - block: Option, - id: SourceIdentifierId, - ) -> Option { - if let Some(block) = block { - // It does not matter in what order we find the labels. - // If there are duplicates: that is checked elsewhere. - for &stmt in h[block].labels.iter() { - if h[h[stmt].label] == h[id] { - return Some(stmt); + root.imports[import_index] + }; + + let import = &mut self.heap[import_id]; + match import { + Import::Module(import) => { + debug_assert!(import.module_id.is_none(), "module import already resolved"); + let target_module_id = symbol_table.resolve_module(&import.module_name) + .expect("module import is resolved by symbol table"); + import.module_id = Some(target_module_id) + }, + Import::Symbols(import) => { + debug_assert!(import.module_id.is_none(), "module of symbol import already resolved"); + let target_module_id = symbol_table.resolve_module(&import.module_name) + .expect("symbol import's module is resolved by symbol table"); + import.module_id = Some(target_module_id); + + for symbol in &mut import.symbols { + debug_assert!(symbol.definition_id.is_none(), "symbol import already resolved"); + let (_, target_definition_id) = symbol_table.resolve_symbol(module_root_id, &symbol.alias) + .expect("symbol import is resolved by symbol table") + .as_definition() + .expect("symbol import does not resolve to namespace symbol"); + symbol.definition_id = Some(target_definition_id); + } } } - if let Some(stmt) = ResolveLabels::find_target(h, h[block].parent_block(h), id) { - return Some(stmt); - } - } - None - } -} - -impl Visitor for ResolveLabels { - fn visit_block_statement(&mut self, h: &mut Heap, stmt: BlockStatementId) -> VisitorResult { - assert_eq!(self.block, h[stmt].parent_block(h)); - let old = self.block; - self.block = Some(stmt); - recursive_block_statement(self, h, stmt)?; - self.block = old; - Ok(()) - } - fn visit_labeled_statement(&mut self, h: &mut Heap, stmt: LabeledStatementId) -> VisitorResult { - assert!(!self.block.is_none()); - self.check_duplicate(h, stmt)?; - recursive_labeled_statement(self, h, stmt) - } - fn visit_while_statement(&mut self, h: &mut Heap, stmt: WhileStatementId) -> VisitorResult { - let old = self.while_enclosure; - self.while_enclosure = Some(stmt); - recursive_while_statement(self, h, stmt)?; - self.while_enclosure = old; - Ok(()) - } - fn visit_break_statement(&mut self, h: &mut Heap, stmt: BreakStatementId) -> VisitorResult { - let the_while; - if let Some(label) = h[stmt].label { - let target = self.get_target(h, label)?; - let target = &h[h[target].body]; - if !target.is_while() { - return Err(ParseError::new( - h[stmt].position, - "Illegal break: target not a while statement", - )); - } - the_while = target.as_while(); - // TODO: check if break is nested under while - } else { - if self.while_enclosure.is_none() { - return Err(ParseError::new( - h[stmt].position, - "Illegal break: no surrounding while statement", - )); - } - the_while = &h[self.while_enclosure.unwrap()]; - // break is always nested under while, by recursive vistor - } - if the_while.in_sync != self.sync_enclosure { - return Err(ParseError::new( - h[stmt].position, - "Illegal break: synchronous statement escape", - )); - } - h[stmt].target = the_while.next; - Ok(()) - } - fn visit_continue_statement( - &mut self, - h: &mut Heap, - stmt: ContinueStatementId, - ) -> VisitorResult { - let the_while; - if let Some(label) = h[stmt].label { - let target = self.get_target(h, label)?; - let target = &h[h[target].body]; - if !target.is_while() { - return Err(ParseError::new( - h[stmt].position, - "Illegal continue: target not a while statement", - )); - } - the_while = target.as_while(); - // TODO: check if continue is nested under while - } else { - if self.while_enclosure.is_none() { - return Err(ParseError::new( - h[stmt].position, - "Illegal continue: no surrounding while statement", - )); - } - the_while = &h[self.while_enclosure.unwrap()]; - // continue is always nested under while, by recursive vistor - } - if the_while.in_sync != self.sync_enclosure { - return Err(ParseError::new( - h[stmt].position, - "Illegal continue: synchronous statement escape", - )); - } - h[stmt].target = Some(the_while.this); - Ok(()) - } - fn visit_synchronous_statement( - &mut self, - h: &mut Heap, - stmt: SynchronousStatementId, - ) -> VisitorResult { - assert!(self.sync_enclosure.is_none()); - self.sync_enclosure = Some(stmt); - recursive_synchronous_statement(self, h, stmt)?; - self.sync_enclosure = None; - Ok(()) - } - fn visit_goto_statement(&mut self, h: &mut Heap, stmt: GotoStatementId) -> VisitorResult { - let target = self.get_target(h, h[stmt].label)?; - if h[target].in_sync != self.sync_enclosure { - return Err(ParseError::new( - h[stmt].position, - "Illegal goto: synchronous statement escape", - )); } - h[stmt].target = Some(target); - Ok(()) - } - fn visit_expression(&mut self, _h: &mut Heap, _expr: ExpressionId) -> VisitorResult { - Ok(()) - } -} -struct AssignableExpressions { - assignable: bool, -} + // All imports in the AST are now annotated. We now use the symbol table + // to construct the type table. -impl AssignableExpressions { - fn new() -> Self { - AssignableExpressions { assignable: false } - } - fn error(&self, position: InputPosition) -> VisitorResult { - Err(ParseError::new(position, "Unassignable expression")) - } -} -impl Visitor for AssignableExpressions { - fn visit_assignment_expression( - &mut self, - h: &mut Heap, - expr: AssignmentExpressionId, - ) -> VisitorResult { - if self.assignable { - self.error(h[expr].position) - } else { - self.assignable = true; - self.visit_expression(h, h[expr].left)?; - self.assignable = false; - self.visit_expression(h, h[expr].right) - } - } - fn visit_conditional_expression( - &mut self, - h: &mut Heap, - expr: ConditionalExpressionId, - ) -> VisitorResult { - if self.assignable { - self.error(h[expr].position) - } else { - recursive_conditional_expression(self, h, expr) - } - } - fn visit_binary_expression(&mut self, h: &mut Heap, expr: BinaryExpressionId) -> VisitorResult { - if self.assignable { - self.error(h[expr].position) - } else { - recursive_binary_expression(self, h, expr) - } - } - fn visit_unary_expression(&mut self, h: &mut Heap, expr: UnaryExpressionId) -> VisitorResult { - if self.assignable { - self.error(h[expr].position) - } else { - match h[expr].operation { - UnaryOperation::PostDecrement - | UnaryOperation::PreDecrement - | UnaryOperation::PostIncrement - | UnaryOperation::PreIncrement => { - self.assignable = true; - recursive_unary_expression(self, h, expr)?; - self.assignable = false; - Ok(()) - } - _ => recursive_unary_expression(self, h, expr), - } - } - } - fn visit_indexing_expression( - &mut self, - h: &mut Heap, - expr: IndexingExpressionId, - ) -> VisitorResult { - let old = self.assignable; - self.assignable = false; - recursive_indexing_expression(self, h, expr)?; - self.assignable = old; - Ok(()) - } - fn visit_slicing_expression( - &mut self, - h: &mut Heap, - expr: SlicingExpressionId, - ) -> VisitorResult { - let old = self.assignable; - self.assignable = false; - recursive_slicing_expression(self, h, expr)?; - self.assignable = old; - Ok(()) - } - fn visit_select_expression(&mut self, h: &mut Heap, expr: SelectExpressionId) -> VisitorResult { - if h[expr].field.is_length() && self.assignable { - return self.error(h[expr].position); - } - let old = self.assignable; - self.assignable = false; - recursive_select_expression(self, h, expr)?; - self.assignable = old; Ok(()) } - fn visit_array_expression(&mut self, h: &mut Heap, expr: ArrayExpressionId) -> VisitorResult { - if self.assignable { - self.error(h[expr].position) - } else { - recursive_array_expression(self, h, expr) - } - } - fn visit_call_expression(&mut self, h: &mut Heap, expr: CallExpressionId) -> VisitorResult { - if self.assignable { - self.error(h[expr].position) - } else { - recursive_call_expression(self, h, expr) - } - } - fn visit_constant_expression( - &mut self, - h: &mut Heap, - expr: ConstantExpressionId, - ) -> VisitorResult { - if self.assignable { - self.error(h[expr].position) - } else { - Ok(()) - } - } - fn visit_variable_expression( - &mut self, - _h: &mut Heap, - _expr: VariableExpressionId, - ) -> VisitorResult { - Ok(()) - } -} - -struct IndexableExpressions { - indexable: bool, -} -impl IndexableExpressions { - fn new() -> Self { - IndexableExpressions { indexable: false } - } - fn error(&self, position: InputPosition) -> VisitorResult { - Err(ParseError::new(position, "Unindexable expression")) - } -} + // TODO: @fix, temporary impl to keep code compilable + pub fn parse(&mut self) -> Result { + assert_eq!(self.modules.len(), 1, "Fix meeeee"); + let root_id = self.modules[0].root_id; + println!("DEBUG: With root id {:?}\nSource: {}", root_id, String::from_utf8_lossy(&self.modules[0].source.input)); -impl Visitor for IndexableExpressions { - fn visit_assignment_expression( - &mut self, - h: &mut Heap, - expr: AssignmentExpressionId, - ) -> VisitorResult { - if self.indexable { - self.error(h[expr].position) - } else { - recursive_assignment_expression(self, h, expr) - } - } - fn visit_conditional_expression( - &mut self, - h: &mut Heap, - expr: ConditionalExpressionId, - ) -> VisitorResult { - let old = self.indexable; - self.indexable = false; - self.visit_expression(h, h[expr].test)?; - self.indexable = old; - self.visit_expression(h, h[expr].true_expression)?; - self.visit_expression(h, h[expr].false_expression) - } - fn visit_binary_expression(&mut self, h: &mut Heap, expr: BinaryExpressionId) -> VisitorResult { - if self.indexable && h[expr].operation != BinaryOperator::Concatenate { - self.error(h[expr].position) - } else { - recursive_binary_expression(self, h, expr) - } - } - fn visit_unary_expression(&mut self, h: &mut Heap, expr: UnaryExpressionId) -> VisitorResult { - if self.indexable { - self.error(h[expr].position) - } else { - recursive_unary_expression(self, h, expr) + if let Err((position, message)) = Self::parse_inner(&mut self.heap, root_id) { + return Err(ParseError2::new_error(&self.modules[0].source, position, &message)) } + Ok(root_id) } - fn visit_indexing_expression( - &mut self, - h: &mut Heap, - expr: IndexingExpressionId, - ) -> VisitorResult { - let old = self.indexable; - self.indexable = true; - self.visit_expression(h, h[expr].subject)?; - self.indexable = false; - self.visit_expression(h, h[expr].index)?; - self.indexable = old; - Ok(()) - } - fn visit_slicing_expression( - &mut self, - h: &mut Heap, - expr: SlicingExpressionId, - ) -> VisitorResult { - let old = self.indexable; - self.indexable = true; - self.visit_expression(h, h[expr].subject)?; - self.indexable = false; - self.visit_expression(h, h[expr].from_index)?; - self.visit_expression(h, h[expr].to_index)?; - self.indexable = old; - Ok(()) - } - fn visit_select_expression(&mut self, h: &mut Heap, expr: SelectExpressionId) -> VisitorResult { - let old = self.indexable; - self.indexable = false; - recursive_select_expression(self, h, expr)?; - self.indexable = old; - Ok(()) - } - fn visit_array_expression(&mut self, h: &mut Heap, expr: ArrayExpressionId) -> VisitorResult { - let old = self.indexable; - self.indexable = false; - recursive_array_expression(self, h, expr)?; - self.indexable = old; - Ok(()) - } - fn visit_call_expression(&mut self, h: &mut Heap, expr: CallExpressionId) -> VisitorResult { - let old = self.indexable; - self.indexable = false; - recursive_call_expression(self, h, expr)?; - self.indexable = old; - Ok(()) - } - fn visit_constant_expression( - &mut self, - h: &mut Heap, - expr: ConstantExpressionId, - ) -> VisitorResult { - if self.indexable { - self.error(h[expr].position) - } else { - Ok(()) - } - } -} - -struct SelectableExpressions { - selectable: bool, -} - -impl SelectableExpressions { - fn new() -> Self { - SelectableExpressions { selectable: false } - } - fn error(&self, position: InputPosition) -> VisitorResult { - Err(ParseError::new(position, "Unselectable expression")) - } -} -impl Visitor for SelectableExpressions { - fn visit_assignment_expression( - &mut self, - h: &mut Heap, - expr: AssignmentExpressionId, - ) -> VisitorResult { - // left-hand side of assignment can be skipped - let old = self.selectable; - self.selectable = false; - self.visit_expression(h, h[expr].right)?; - self.selectable = old; - Ok(()) - } - fn visit_conditional_expression( - &mut self, - h: &mut Heap, - expr: ConditionalExpressionId, - ) -> VisitorResult { - let old = self.selectable; - self.selectable = false; - self.visit_expression(h, h[expr].test)?; - self.selectable = old; - self.visit_expression(h, h[expr].true_expression)?; - self.visit_expression(h, h[expr].false_expression) - } - fn visit_binary_expression(&mut self, h: &mut Heap, expr: BinaryExpressionId) -> VisitorResult { - if self.selectable && h[expr].operation != BinaryOperator::Concatenate { - self.error(h[expr].position) - } else { - recursive_binary_expression(self, h, expr) - } - } - fn visit_unary_expression(&mut self, h: &mut Heap, expr: UnaryExpressionId) -> VisitorResult { - if self.selectable { - self.error(h[expr].position) - } else { - recursive_unary_expression(self, h, expr) - } - } - fn visit_indexing_expression( - &mut self, - h: &mut Heap, - expr: IndexingExpressionId, - ) -> VisitorResult { - let old = self.selectable; - self.selectable = false; - recursive_indexing_expression(self, h, expr)?; - self.selectable = old; - Ok(()) - } - fn visit_slicing_expression( - &mut self, - h: &mut Heap, - expr: SlicingExpressionId, - ) -> VisitorResult { - let old = self.selectable; - self.selectable = false; - recursive_slicing_expression(self, h, expr)?; - self.selectable = old; - Ok(()) - } - fn visit_select_expression(&mut self, h: &mut Heap, expr: SelectExpressionId) -> VisitorResult { - let old = self.selectable; - self.selectable = false; - recursive_select_expression(self, h, expr)?; - self.selectable = old; - Ok(()) - } - fn visit_array_expression(&mut self, h: &mut Heap, expr: ArrayExpressionId) -> VisitorResult { - let old = self.selectable; - self.selectable = false; - 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(()) - } - } -} - -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 { - let mut lex = Lexer::new(self.source); - let pd = lex.consume_protocol_description(h)?; + pub fn parse_inner(h: &mut Heap, pd: RootId) -> VisitorResult { NestedSynchronousStatements::new().visit_protocol_description(h, pd)?; ChannelStatementOccurrences::new().visit_protocol_description(h, pd)?; FunctionStatementReturns::new().visit_protocol_description(h, pd)?; @@ -1817,7 +213,8 @@ impl<'a> Parser<'a> { AssignableExpressions::new().visit_protocol_description(h, pd)?; IndexableExpressions::new().visit_protocol_description(h, pd)?; SelectableExpressions::new().visit_protocol_description(h, pd)?; - Ok(pd) + + Ok(()) } } @@ -1835,16 +232,14 @@ mod tests { let resource = resource.expect("read testdata filepath"); // println!(" * running: {}", &resource); let path = Path::new(&resource); - let mut heap = Heap::new(); let mut source = InputSource::from_file(&path).unwrap(); // println!("DEBUG -- input:\n{}", String::from_utf8_lossy(&source.input)); - let mut parser = Parser::new(&mut source); - match parser.parse(&mut heap) { + let mut parser = Parser::new_with_source(source).expect("parse source"); + match parser.parse() { Ok(_) => {} Err(err) => { println!(" > file: {}", &resource); - println!("{}", err.display(&source)); - println!("{:?}", err); + println!("{}", err); assert!(false); } } @@ -1857,12 +252,10 @@ mod tests { let resource = resource.expect("read testdata filepath"); let path = Path::new(&resource); let expect = path.with_extension("txt"); - 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) { + let mut parser = Parser::new_with_source(source).expect("construct parser"); + match parser.parse() { Ok(pd) => { - println!("{:?}", heap[pd]); println!("Expected parse error:"); let mut cev: Vec = Vec::new(); @@ -1872,18 +265,15 @@ mod tests { assert!(false); } Err(err) => { - println!("{:?}", err); - - let mut vec: Vec = Vec::new(); - err.write(&source, &mut vec).unwrap(); - println!("{}", String::from_utf8_lossy(&vec)); + let expected = format!("{}", err); + println!("{}", &expected); let mut cev: Vec = Vec::new(); let mut f = File::open(expect).unwrap(); f.read_to_end(&mut cev).unwrap(); println!("{}", String::from_utf8_lossy(&cev)); - assert_eq!(vec, cev); + assert_eq!(expected.as_bytes(), cev); } } } @@ -1894,9 +284,8 @@ mod tests { for resource in TestFileIter::new("testdata/parser/counterexamples", "pdl") { let resource = resource.expect("read testdata filepath"); 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); + let source = InputSource::from_file(&path).unwrap(); + let mut parser = Parser::new_with_source(source).expect("construct parser"); fn print_header(s: &str) { println!("{}", "=".repeat(80)); @@ -1904,20 +293,17 @@ mod tests { println!("{}", "=".repeat(80)); } - match parser.parse(&mut heap) { + match parser.parse() { Ok(parsed) => { print_header(&resource); - println!("\n SUCCESS\n\n --- source:\n{}", String::from_utf8_lossy(&source.input)); + println!("\n SUCCESS\n\n --- source:\n{}", String::from_utf8_lossy(&parser.modules[0].source.input)); }, Err(err) => { print_header(&resource); - - let mut err_buf = Vec::new(); - err.write(&source, &mut err_buf); println!( "\n FAILURE\n\n --- error:\n{}\n --- source:\n{}", - String::from_utf8_lossy(&err_buf), - String::from_utf8_lossy(&source.input) + err, + String::from_utf8_lossy(&parser.modules[0].source.input) ) } }