donet_core/parser/
pipeline.rs1use super::ast;
24use crate::dconfig::*;
25use codespan_reporting::diagnostic::Diagnostic;
26use codespan_reporting::diagnostic::Severity;
27use codespan_reporting::files::{self, SimpleFiles};
28use codespan_reporting::term;
29use term::termcolor::{ColorChoice, StandardStream};
30
31#[derive(Debug, Default, Clone, PartialEq, Eq)]
34pub(crate) enum PipelineStage {
35 #[default]
36 Parser, SemanticAnalyzer,
38}
39
40impl PipelineStage {
41 pub(crate) fn next(&self) -> Self {
42 match self {
43 PipelineStage::Parser => PipelineStage::SemanticAnalyzer,
44 PipelineStage::SemanticAnalyzer => panic!("No next stage in pipeline."),
45 }
46 }
47}
48
49pub(crate) struct PipelineData<'a> {
54 dc_parser_config: DCFileConfig,
55 stage: PipelineStage,
56 _writer: StandardStream,
57 _config: term::Config,
58 diagnostics_enabled: bool,
59 errors_emitted: usize,
60 pub files: SimpleFiles<&'a str, &'a str>,
61 current_file: usize,
62 pub syntax_trees: Vec<ast::Root>,
63}
64
65impl Drop for PipelineData<'_> {
70 fn drop(&mut self) {
71 if self.errors_emitted > 0 {
72 let diag = Diagnostic::error().with_message(format!(
73 "Failed to read DC files due to {} previous errors.",
74 self.errors_emitted
75 ));
76
77 self.emit_diagnostic(diag).expect("Failed to emit diagnostic.");
78 }
79 }
80}
81
82impl From<DCFileConfig> for PipelineData<'_> {
83 fn from(value: DCFileConfig) -> Self {
84 Self {
85 dc_parser_config: value,
86 stage: PipelineStage::default(),
87 _writer: StandardStream::stderr(ColorChoice::Always),
88 _config: term::Config::default(),
89 diagnostics_enabled: {
90 cfg_if! {
92 if #[cfg(test)] {
93 false
94 } else {
95 true
96 }
97 }
98 },
99 errors_emitted: 0,
100 files: SimpleFiles::new(),
101 current_file: 0,
102 syntax_trees: vec![],
103 }
104 }
105}
106
107impl DCFileConfigAccessor for PipelineData<'_> {
108 fn get_dc_config(&self) -> &DCFileConfig {
109 &self.dc_parser_config
110 }
111}
112
113impl PipelineData<'_> {
114 pub(crate) fn emit_diagnostic(&mut self, diag: Diagnostic<usize>) -> Result<(), files::Error> {
116 if diag.severity == Severity::Error {
117 self.errors_emitted += 1;
118 }
119 if !self.diagnostics_enabled {
120 return Ok(());
121 }
122 term::emit(&mut self._writer.lock(), &self._config, &self.files, &diag)
123 }
124
125 #[inline(always)]
126 pub(crate) fn current_stage(&self) -> PipelineStage {
127 self.stage.clone()
128 }
129
130 pub(crate) fn next_stage(&mut self) {
131 self.stage = self.stage.next();
132 self.current_file = 0;
133 }
134
135 #[inline(always)]
136 pub(crate) fn current_file(&self) -> usize {
137 self.current_file
138 }
139
140 pub(crate) fn next_file(&mut self) {
141 self.current_file += 1
142 }
143
144 #[inline(always)]
145 pub(crate) fn failing(&self) -> bool {
146 self.errors_emitted > 0
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn next_stage_state() {
156 let mut pipeline: PipelineData = DCFileConfig::default().into();
157
158 pipeline.next_file(); pipeline.next_stage(); assert_eq!(pipeline.stage, PipelineStage::SemanticAnalyzer);
163 assert_eq!(pipeline.current_file, 0);
164 }
165}