Changeset - d25df42a65d3
[Not reviewed]
1 6 0
MH - 4 years ago 2021-03-08 09:55:18
contact@maxhenger.nl
remove concept of declaration AST nodes
7 files changed with 1 insertions and 444 deletions:
0 comments (0 inline, 0 general)
src/protocol/ast.rs
Show inline comments
 
@@ -81,10 +81,6 @@ define_new_ast_id!(ConstantExpressionId, ExpressionId);
 
define_new_ast_id!(CallExpressionId, ExpressionId);
 
define_new_ast_id!(VariableExpressionId, ExpressionId);
 

	
 
define_aliased_ast_id!(DeclarationId, Id<Declaration>); // TODO: @cleanup
 
define_new_ast_id!(DefinedDeclarationId, DeclarationId);
 
define_new_ast_id!(ImportedDeclarationId, DeclarationId);
 

	
 
// TODO: @cleanup - pub qualifiers can be removed once done
 
#[derive(Debug, serde::Serialize, serde::Deserialize)]
 
pub struct Heap {
 
@@ -102,7 +98,6 @@ pub struct Heap {
 
    pub(crate) definitions: Arena<Definition>,
 
    pub(crate) statements: Arena<Statement>,
 
    pub(crate) expressions: Arena<Expression>,
 
    declarations: Arena<Declaration>,
 
}
 

	
 
impl Heap {
 
@@ -118,7 +113,6 @@ impl Heap {
 
            definitions: Arena::new(),
 
            statements: Arena::new(),
 
            expressions: Arena::new(),
 
            declarations: Arena::new(),
 
        }
 
    }
 
    pub fn alloc_type_annotation(
 
@@ -440,24 +434,6 @@ impl Heap {
 
    pub fn alloc_protocol_description(&mut self, f: impl FnOnce(RootId) -> Root) -> RootId {
 
        self.protocol_descriptions.alloc_with_id(|id| f(id))
 
    }
 
    pub fn alloc_imported_declaration(
 
        &mut self,
 
        f: impl FnOnce(ImportedDeclarationId) -> ImportedDeclaration,
 
    ) -> ImportedDeclarationId {
 
        ImportedDeclarationId(self.declarations.alloc_with_id(|id| {
 
            Declaration::Imported(f(ImportedDeclarationId(id)))
 
        }))
 
    }
 
    pub fn alloc_defined_declaration(
 
        &mut self,
 
        f: impl FnOnce(DefinedDeclarationId) -> DefinedDeclaration,
 
    ) -> DefinedDeclarationId {
 
        DefinedDeclarationId(
 
            self.declarations.alloc_with_id(|id| {
 
                Declaration::Defined(f(DefinedDeclarationId(id)))
 
            }),
 
        )
 
    }
 
}
 

	
 
impl Index<RootId> for Heap {
 
@@ -838,13 +814,6 @@ impl IndexMut<VariableExpressionId> for Heap {
 
    }
 
}
 

	
 
impl Index<DeclarationId> for Heap {
 
    type Output = Declaration;
 
    fn index(&self, index: DeclarationId) -> &Self::Output {
 
        &self.declarations[index]
 
    }
 
}
 

	
 
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 
pub struct Root {
 
    pub this: RootId,
 
@@ -853,8 +822,6 @@ pub struct Root {
 
    pub pragmas: Vec<PragmaId>,
 
    pub imports: Vec<ImportId>,
 
    pub definitions: Vec<DefinitionId>,
 
    // Pase 2: linker
 
    pub declarations: Vec<DeclarationId>,
 
}
 

	
 
impl Root {
 
@@ -866,25 +833,6 @@ impl Root {
 
        }
 
        None
 
    }
 
    pub fn get_declaration(&self, h: &Heap, id: &Identifier) -> Option<DeclarationId> {
 
        for declaration_id in self.declarations.iter() {
 
            let declaration = &h[*declaration_id];
 
            if declaration.identifier().value == id.value {
 
                return Some(*declaration_id);
 
            }
 
        }
 
        None
 
    }
 
    pub fn get_declaration_namespaced(&self, h: &Heap, id: &NamespacedIdentifier) -> Option<DeclarationId> {
 
        for declaration_id in self.declarations.iter() {
 
            let declaration = &h[*declaration_id];
 
            // TODO: @fixme
 
            if declaration.identifier().value == id.value {
 
                return Some(*declaration_id);
 
            }
 
        }
 
        None
 
    }
 
}
 

	
 
impl SyntaxElement for Root {
 
@@ -1555,52 +1503,6 @@ impl SyntaxElement for Function {
 
    }
 
}
 

	
 
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 
pub enum Declaration {
 
    Defined(DefinedDeclaration),
 
    Imported(ImportedDeclaration),
 
}
 

	
 
impl Declaration {
 
    pub fn signature(&self) -> &Signature {
 
        match self {
 
            Declaration::Defined(decl) => &decl.signature,
 
            Declaration::Imported(decl) => &decl.signature,
 
        }
 
    }
 
    pub fn identifier(&self) -> &Identifier {
 
        self.signature().identifier()
 
    }
 
    pub fn is_component(&self) -> bool {
 
        self.signature().is_component()
 
    }
 
    pub fn is_function(&self) -> bool {
 
        self.signature().is_function()
 
    }
 
    pub fn as_defined(&self) -> &DefinedDeclaration {
 
        match self {
 
            Declaration::Defined(result) => result,
 
            _ => panic!("Unable to cast `Declaration` to `DefinedDeclaration`"),
 
        }
 
    }
 
}
 

	
 
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 
pub struct DefinedDeclaration {
 
    pub this: DefinedDeclarationId,
 
    // Phase 2: linker
 
    pub definition: DefinitionId,
 
    pub signature: Signature,
 
}
 

	
 
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 
pub struct ImportedDeclaration {
 
    pub this: ImportedDeclarationId,
 
    // Phase 2: linker
 
    pub import: ImportId,
 
    pub signature: Signature,
 
}
 

	
 
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 
pub enum Signature {
 
    Component(ComponentSignature),
src/protocol/ast_printer.rs
Show inline comments
 
@@ -2,7 +2,6 @@ use std::fmt::{Debug, Display, Write};
 
use std::io::Write as IOWrite;
 

	
 
use super::ast::*;
 
use std::borrow::Borrow;
 

	
 
const INDENT: usize = 2;
 

	
src/protocol/lexer.rs
Show inline comments
 
@@ -2050,7 +2050,6 @@ impl Lexer<'_> {
 
            pragmas,
 
            imports,
 
            definitions,
 
            declarations: Vec::new(),
 
        }))
 
    }
 
}
 
@@ -2058,7 +2057,7 @@ impl Lexer<'_> {
 
#[cfg(test)]
 
mod tests {
 
    use crate::protocol::ast::*;
 
    use crate::protocol::{ast, lexer::*};
 
    use crate::protocol::lexer::*;
 
    use crate::protocol::inputsource::*;
 

	
 
    #[test]
src/protocol/library.rs
Show inline comments
 
deleted file
src/protocol/mod.rs
Show inline comments
 
@@ -3,7 +3,6 @@ mod arena;
 
mod eval;
 
pub(crate) mod inputsource;
 
// mod lexer;
 
mod library;
 
mod parser;
 

	
 
// TODO: Remove when not benchmarking
src/protocol/parser/depth_visitor.rs
Show inline comments
 
use crate::protocol::ast::*;
 
use crate::protocol::inputsource::*;
 
use crate::protocol::library;
 

	
 
// The following indirection is needed due to a bug in the cbindgen tool.
 
type Unit = ();
 
@@ -780,142 +779,6 @@ impl Visitor for CheckBuiltinOccurrences {
 
    }
 
}
 

	
 
pub(crate) struct BuildSymbolDeclarations {
 
    declarations: Vec<DeclarationId>,
 
}
 

	
 
impl BuildSymbolDeclarations {
 
    pub(crate) 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 id.value == h[old].identifier().value {
 
                return match h[decl].clone() {
 
                    Declaration::Defined(defined) => Err((
 
                        h[defined.definition].position(),
 
                        format!("Defined symbol clash: {}", String::from_utf8_lossy(&id.value)),
 
                    )),
 
                    Declaration::Imported(imported) => Err((
 
                        h[imported.import].position(),
 
                        format!("Imported symbol clash: {}", String::from_utf8_lossy(&id.value)),
 
                    )),
 
                };
 
            }
 
        }
 
        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!());
 
        // TODO: Implement
 
        let vec = library::get_declarations(h, import);
 
        if let Err(_err)= vec {
 
            return Err((h[import].position(), "Failed to perform import".to_string()))
 
        }
 

	
 
        // Destructively iterate over the vector
 
        for decl in vec.unwrap() {
 
            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(())
 
    }
 
}
 

	
 
pub(crate) struct LinkCallExpressions {
 
    pd: Option<RootId>,
 
    composite: bool,
 
    new_statement: bool,
 
}
 

	
 
impl LinkCallExpressions {
 
    pub(crate) fn new() -> Self {
 
        LinkCallExpressions { pd: None, composite: false, new_statement: false }
 
    }
 
    fn get_declaration(
 
        &self,
 
        h: &Heap,
 
        id: &Identifier,
 
    ) -> Result<DeclarationId, VisitorError> {
 
        match h[self.pd.unwrap()].get_declaration(h, &id) {
 
            Some(id) => Ok(id),
 
            None => Err((id.position, "Unresolved method".to_string())),
 
        }
 
    }
 
    fn get_declaration_namespaced(
 
        &self, h: &Heap, id: &NamespacedIdentifier
 
    ) -> Result<DeclarationId, VisitorError> {
 
        // TODO: @fixme
 
        match h[self.pd.unwrap()].get_declaration_namespaced(h, id) {
 
            Some(id) => Ok(id),
 
            None => Err((id.position, "Unresolved method".to_string()))
 
        }
 
    }
 
}
 

	
 
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: ComponentId) -> 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 {
 
            // TODO: @symbol_table
 
            let decl = self.get_declaration_namespaced(h, &id.identifier)?;
 
            if self.new_statement && h[decl].is_function() {
 
                return Err((id.identifier.position, "Illegal call expression".to_string()));
 
            }
 
            if !self.new_statement && h[decl].is_component() {
 
                return Err((id.identifier.position, "Illegal call expression".to_string()));
 
            }
 
            // Set the corresponding declaration of the call
 
            // TODO: This should not be necessary anymore once parser is rewritten
 
            // h[expr]. = 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(())
 
    }
 
}
 

	
 
pub(crate) struct BuildScope {
 
    scope: Option<Scope>,
 
}
 
@@ -968,145 +831,6 @@ impl Visitor for BuildScope {
 
    }
 
}
 

	
 
pub(crate) struct ResolveVariables {
 
    scope: Option<Scope>,
 
}
 

	
 
impl ResolveVariables {
 
    pub(crate) fn new() -> Self {
 
        ResolveVariables { scope: None }
 
    }
 
    fn get_variable(&self, h: &Heap, id: &Identifier) -> Result<VariableId, VisitorError> {
 
        if let Some(var) = self.find_variable(h, id) {
 
            Ok(var)
 
        } else {
 
            Err((id.position, "Unresolved variable".to_string()))
 
        }
 
    }
 
    fn find_variable(&self, h: &Heap, id: &Identifier) -> Option<VariableId> {
 
        ResolveVariables::find_variable_impl(h, self.scope, id)
 
    }
 
    fn find_variable_impl(
 
        h: &Heap,
 
        scope: Option<Scope>,
 
        id: &Identifier,
 
    ) -> Option<VariableId> {
 
        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)
 
            } 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(())
 
    }
 
    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((id.position, "Declared variable clash".to_string()));
 
            }
 
        }
 
        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((id.position, "Declared variable clash".to_string()));
 
        }
 
        // 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((id.position, "Declared variable clash".to_string()));
 
            }
 
            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((id.position, "Declared variable clash".to_string()));
 
            }
 
            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::Regular(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, BlockStatementId(stmt.upcast())))); // TODO: WRONG!
 
        recursive_synchronous_statement(self, h, stmt)?;
 
        self.scope = old;
 
        Ok(())
 
    }
 
    fn visit_variable_expression(
 
        &mut self,
 
        h: &mut Heap,
 
        expr: VariableExpressionId,
 
    ) -> VisitorResult {
 
        let ident = Identifier{ position: Default::default(), value: h[expr].identifier.value.clone() };
 
        let var = self.get_variable(h, &ident)?;
 
        h[expr].declaration = Some(var);
 
        Ok(())
 
    }
 
}
 

	
 
pub(crate) struct UniqueStatementId(StatementId);
 

	
 
pub(crate) struct LinkStatements {
src/protocol/parser/mod.rs
Show inline comments
 
@@ -16,7 +16,6 @@ use crate::protocol::inputsource::*;
 
use crate::protocol::lexer::*;
 

	
 
use std::collections::HashMap;
 
use crate::protocol::parser::visitor::Ctx;
 
use crate::protocol::ast_printer::ASTWriter;
 

	
 
// TODO: @fixme, pub qualifier
0 comments (0 inline, 0 general)