Skip to content

Commit

Permalink
parser: share diagnostic store between parent and children AstGens
Browse files Browse the repository at this point in the history
  • Loading branch information
feds01 committed Aug 31, 2023
1 parent f43f866 commit 72beee8
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 53 deletions.
20 changes: 7 additions & 13 deletions compiler/hash-parser/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,18 @@ pub(crate) mod error;
pub(crate) mod expected;
pub(crate) mod warning;

use hash_reporting::{
diagnostic::{AccessToDiagnosticsMut, DiagnosticStore, DiagnosticsMut},
reporter::Reports,
};
use hash_reporting::diagnostic::{AccessToDiagnostics, DiagnosticCellStore};

use self::{error::ParseError, warning::ParseWarning};
use crate::parser::AstGen;

impl<'stream, 'resolver> AstGen<'stream, 'resolver> {
pub(super) fn into_reports(mut self) -> Reports {
self.diagnostics().into_reports(Reports::from, Reports::from)
}
}
/// Shorthand for the parser diagnostics.
pub type ParserDiagnostics = DiagnosticCellStore<ParseError, ParseWarning>;

impl<'stream, 'resolver> AccessToDiagnosticsMut for AstGen<'stream, 'resolver> {
type Diagnostics = DiagnosticStore<ParseError, ParseWarning>;
impl<'stream, 'resolver> AccessToDiagnostics for AstGen<'stream, 'resolver> {
type Diagnostics = ParserDiagnostics;

fn diagnostics(&mut self) -> &mut Self::Diagnostics {
&mut self.diagnostics
fn diagnostics(&self) -> &Self::Diagnostics {
self.diagnostics
}
}
20 changes: 12 additions & 8 deletions compiler/hash-parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ use hash_pipeline::{
settings::CompilerStageKind,
workspace::Workspace,
};
use hash_reporting::{diagnostic::AccessToDiagnosticsMut, report::Report};
use hash_reporting::{
diagnostic::{AccessToDiagnosticsMut, Diagnostics},
report::Report,
reporter::Reports,
};
use hash_source::{InteractiveId, ModuleId, ModuleKind, SourceId};
use hash_target::size::Size;
use hash_utils::{
Expand All @@ -29,6 +33,8 @@ use import_resolver::ImportResolver;
use parser::AstGen;
use source::ParseSource;

use crate::diagnostics::ParserDiagnostics;

/// The [Parser] stage is responsible for parsing the source code into an
/// abstract syntax tree (AST). The parser will also perform some basic
/// semantic analysis, such as resolving imports, and some other basic
Expand Down Expand Up @@ -231,8 +237,6 @@ pub enum ParserAction {
/// Parse a specific source specified by [ParseSource].
fn parse_source(source: ParseSource, sender: Sender<ParserAction>) {
let source_id = source.id();
let contents = source.contents();

let mut timings = ParseTimings::default();

// @@Future: we currently don't support cross compilation, which
Expand All @@ -243,7 +247,7 @@ fn parse_source(source: ParseSource, sender: Sender<ParserAction>) {
let ptr_byte_width = Size::from_bytes(std::mem::size_of::<usize>());

// Lex the contents of the module or interactive block
let mut lexer = Lexer::new(&contents, source_id, ptr_byte_width);
let mut lexer = Lexer::new(source.contents(), source_id, ptr_byte_width);
let tokens = time_item(&mut timings, "tokenise", |_| lexer.tokenise());

// Check if the lexer has errors...
Expand All @@ -257,8 +261,8 @@ fn parse_source(source: ParseSource, sender: Sender<ParserAction>) {
// Create a new import resolver in the event of more modules that
// are encountered whilst parsing this module.
let resolver = ImportResolver::new(source_id, source.path(), sender);

let mut gen = AstGen::new(&tokens, &trees, &resolver);
let diagnostics = ParserDiagnostics::new();
let mut gen = AstGen::new(&tokens, &trees, &resolver, &diagnostics);

// Perform the parsing operation now... and send the result through the
// message queue, regardless of it being an error or not.
Expand All @@ -269,7 +273,7 @@ fn parse_source(source: ParseSource, sender: Sender<ParserAction>) {
ParserAction::SetModuleNode {
id: id.into(),
node,
diagnostics: gen.into_reports(),
diagnostics: diagnostics.into_reports(Reports::from, Reports::from),
timings,
}
}
Expand All @@ -278,7 +282,7 @@ fn parse_source(source: ParseSource, sender: Sender<ParserAction>) {
ParserAction::SetInteractiveNode {
id: id.into(),
node,
diagnostics: gen.into_reports(),
diagnostics: diagnostics.into_reports(Reports::from, Reports::from),
timings,
}
}
Expand Down
4 changes: 1 addition & 3 deletions compiler/hash-parser/src/parser/block.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Hash Compiler AST generation sources. This file contains the sources to the
//! logic that transforms tokens into an AST.
use hash_ast::ast::*;
use hash_reporting::diagnostic::{AccessToDiagnosticsMut, DiagnosticsMut};
use hash_reporting::diagnostic::AccessToDiagnostics;
use hash_token::{delimiter::Delimiter, keyword::Keyword, TokenKind};
use hash_utils::thin_vec::thin_vec;

Expand All @@ -15,7 +15,6 @@ impl<'stream, 'resolver> AstGen<'stream, 'resolver> {
let mut gen = self.parse_delim_tree(Delimiter::Brace, Some(ParseErrorKind::Block))?;

let block = gen.parse_body_block_inner();
self.diagnostics.merge_diagnostics(gen.diagnostics);

Ok(self.node_with_span(Block::Body(block), self.current_pos()))
}
Expand All @@ -27,7 +26,6 @@ impl<'stream, 'resolver> AstGen<'stream, 'resolver> {
let mut gen = self.parse_delim_tree(Delimiter::Brace, Some(ParseErrorKind::Block))?;

let block = gen.parse_body_block_inner();
self.merge_diagnostics(gen.diagnostics);

Ok(self.node_with_span(block, self.current_pos()))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/hash-parser/src/parser/expr.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Hash Compiler AST generation sources. This file contains the sources to the
//! logic that transforms tokens into an AST.
use hash_ast::ast::*;
use hash_reporting::diagnostic::AccessToDiagnosticsMut;
use hash_reporting::diagnostic::AccessToDiagnostics;
use hash_source::location::ByteRange;
use hash_token::{delimiter::Delimiter, keyword::Keyword, Token, TokenKind};
use hash_utils::thin_vec::thin_vec;
Expand Down
21 changes: 6 additions & 15 deletions compiler/hash-parser/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ mod ty;
use std::cell::Cell;

use hash_ast::ast::*;
use hash_reporting::diagnostic::{AccessToDiagnosticsMut, DiagnosticStore};
use hash_reporting::diagnostic::AccessToDiagnostics;
use hash_source::location::{ByteRange, Span};
use hash_token::{delimiter::Delimiter, Token, TokenKind};
use hash_utils::thin_vec::{thin_vec, ThinVec};
Expand All @@ -24,7 +24,7 @@ use crate::{
diagnostics::{
error::{ParseError, ParseErrorKind, ParseResult},
expected::ExpectedItem,
warning::ParseWarning,
ParserDiagnostics,
},
import_resolver::ImportResolver,
};
Expand Down Expand Up @@ -96,7 +96,7 @@ pub struct AstGen<'stream, 'resolver> {
pub(crate) resolver: &'resolver ImportResolver<'resolver>,

/// Collected diagnostics for the current [AstGen]
pub(crate) diagnostics: DiagnosticStore<ParseError, ParseWarning>,
pub(crate) diagnostics: &'stream ParserDiagnostics,
}

/// Implementation of the [AstGen] with accompanying functions to parse specific
Expand All @@ -107,6 +107,7 @@ impl<'stream, 'resolver> AstGen<'stream, 'resolver> {
stream: &'stream [Token],
token_trees: &'stream [Vec<Token>],
resolver: &'resolver ImportResolver,
diagnostics: &'stream ParserDiagnostics,
) -> Self {
// We compute the `parent_span` from the given strem.
// If the stream has no tokens, then we assume that the
Expand All @@ -116,14 +117,7 @@ impl<'stream, 'resolver> AstGen<'stream, 'resolver> {
_ => ByteRange::default(),
};

Self {
stream,
token_trees,
offset: Cell::new(0),
parent_span,
resolver,
diagnostics: DiagnosticStore::default(),
}
Self { stream, token_trees, offset: Cell::new(0), parent_span, resolver, diagnostics }
}

/// Create new AST generator from a provided token stream with inherited
Expand All @@ -136,7 +130,7 @@ impl<'stream, 'resolver> AstGen<'stream, 'resolver> {
offset: Cell::new(0),
parent_span,
resolver: self.resolver,
diagnostics: DiagnosticStore::default(),
diagnostics: self.diagnostics,
}
}

Expand Down Expand Up @@ -344,9 +338,6 @@ impl<'stream, 'resolver> AstGen<'stream, 'resolver> {
if !other.has_errors() && other.has_token() {
other.maybe_add_error::<()>(other.expected_eof());
}

// Now we will merge this `other` generator with ours...
self.merge_diagnostics(other.diagnostics);
}

/// Generate an error representing that the current generator unexpectedly
Expand Down
2 changes: 1 addition & 1 deletion compiler/hash-parser/src/parser/pat.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Hash Compiler AST generation sources. This file contains the sources to the
//! logic that transforms tokens into an AST.
use hash_ast::{ast::*, origin::PatOrigin};
use hash_reporting::diagnostic::AccessToDiagnosticsMut;
use hash_reporting::diagnostic::AccessToDiagnostics;
use hash_source::{identifier::IDENTS, location::ByteRange};
use hash_token::{delimiter::Delimiter, keyword::Keyword, Token, TokenKind};
use hash_utils::thin_vec::thin_vec;
Expand Down
2 changes: 1 addition & 1 deletion compiler/hash-parser/src/parser/ty.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Hash Compiler AST generation sources. This file contains the sources to the
//! logic that transforms tokens into an AST.
use hash_ast::ast::*;
use hash_reporting::diagnostic::AccessToDiagnosticsMut;
use hash_reporting::diagnostic::AccessToDiagnostics;
use hash_source::identifier::IDENTS;
use hash_token::{delimiter::Delimiter, keyword::Keyword, Token, TokenKind};
use hash_utils::thin_vec::thin_vec;
Expand Down
6 changes: 3 additions & 3 deletions compiler/hash-parser/src/source.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Self hosted hash parser, this function contains the implementations for
//! `hash-ast` which provides a general interface to write a parser.

use std::{borrow::Cow, path::PathBuf};
use std::path::PathBuf;

use hash_ast::node_map::NodeMap;
use hash_source::{SourceId, SourceMap};
Expand Down Expand Up @@ -52,8 +52,8 @@ impl ParseSource {
}

/// Get the contents from the [ParseSource]
pub fn contents(&self) -> Cow<str> {
Cow::Borrowed(self.contents.as_str())
pub fn contents(&self) -> &str {
self.contents.as_str()
}

/// Get the associated [SourceId] from the [ParseSource]
Expand Down
4 changes: 4 additions & 0 deletions compiler/hash-reporting/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ pub trait AccessToDiagnostics {
self.diagnostics().add_error(error)
}

fn maybe_add_error<T>(&mut self, value: Result<T, <Self::Diagnostics as Diagnostics>::Error>) {
self.diagnostics().maybe_add_error(value)
}

fn add_warning(&self, warning: <Self::Diagnostics as Diagnostics>::Warning) {
self.diagnostics().add_warning(warning)
}
Expand Down
16 changes: 8 additions & 8 deletions tests/cases/parser/blocks/parenthesised_match_statement.hash
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// stage=parse, warnings=ignore
// stage=parse, warnings=compare

b := ((match some_struct {
Dog(name, age = 6) => match name {
"Viktor" => print("Viktor is 6");
"Constantine" => print("Kostya is 6");
"Alexander" => print("Sanya is 6");
name => print(name + " is 6");
};
Dog(name, age) => do_something_with_name();
_ => unreachable();
"Viktor" => print("Viktor is 6"),
"Constantine" => print("Kostya is 6"),
"Alexander" => print("Sanya is 6"),
name => print(name + " is 6")
},
Dog(name, age) => do_something_with_name(),
_ => unreachable()
}));
25 changes: 25 additions & 0 deletions tests/cases/parser/blocks/parenthesised_match_statement.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
warn: unnecessary parentheses around block
--> $DIR/parenthesised_match_statement.hash:3:8
2 |
3 | b := ((match some_struct {
| _________-
4 | | Dog(name, age = 6) => match name {
5 | | "Viktor" => print("Viktor is 6"),
... |
10 | | Dog(name, age) => do_something_with_name(),
11 | | _ => unreachable()
12 | | }));
| |__-

warn: unnecessary parentheses around block
--> $DIR/parenthesised_match_statement.hash:3:8
2 |
3 | b := ((match some_struct {
| _________-
4 | | Dog(name, age = 6) => match name {
5 | | "Viktor" => print("Viktor is 6"),
... |
10 | | Dog(name, age) => do_something_with_name(),
11 | | _ => unreachable()
12 | | }));
| |__-

0 comments on commit 72beee8

Please sign in to comment.