1use crate::*;
7use scarf_syntax::SpanRelation;
8use std::collections::HashMap;
9use std::io;
10use std::path::{Path, PathBuf};
11
12const DEFAULT_TIMESCALE: Timescale = Timescale::new_default(
13 (TimescaleValue::One, TimescaleUnit::NS),
14 (TimescaleValue::One, TimescaleUnit::NS),
15);
16
17const DEFAULT_NETTYPE: DefaultNettype = DefaultNettype::Wire;
18
19const DEFAULT_UNCONNECTED_DRIVE: UnconnectedDrive =
20 UnconnectedDrive::NoUnconnected;
21
22#[derive(Clone, Debug)]
24pub struct Define<'a> {
25 pub name: SpannedString<'a>,
26 pub body: DefineBody<'a>,
27}
28
29impl<'a> Define<'a> {
30 pub fn is_from_command_line(&self) -> bool {
34 self.name.1.file == ""
35 }
36}
37
38#[derive(Clone, Debug)]
45pub enum DefineBody<'a> {
46 Empty,
47 Text(Vec<SpannedToken<'a>>),
48 Function(DefineFunction<'a>),
49}
50
51#[derive(Clone, Debug)]
53pub struct DefineFunction<'a> {
54 pub args: Vec<(
57 SpannedString<'a>,
58 Option<(
59 Span<'a>, Vec<SpannedToken<'a>>,
61 )>,
62 )>,
63 pub body: Option<Vec<SpannedToken<'a>>>,
65}
66
67impl<'a> DefineBody<'a> {
68 pub fn get_tokens(
74 &self,
75 ) -> (
76 Vec<SpannedToken<'a>>,
77 Option<Vec<(SpannedString<'a>, Option<Vec<SpannedToken<'a>>>)>>,
78 ) {
79 match self {
80 DefineBody::Empty => (vec![], None),
81 DefineBody::Text(token_vec) => (token_vec.clone(), None),
82 DefineBody::Function(def_func) => {
83 let function_args = def_func
84 .args
85 .iter()
86 .map(|(a, b)| match b {
87 Some((_, tokens)) => (a.clone(), Some(tokens.clone())),
88 None => (a.clone(), None),
89 })
90 .collect();
91 match &def_func.body {
92 Some(token_vec) => (token_vec.clone(), Some(function_args)),
93 None => (vec![], Some(function_args)),
94 }
95 }
96 }
97 }
98}
99
100#[derive(Clone)]
102pub struct LineDirective<'a> {
103 pub directive_file_name: &'a str,
105 pub directive_line_number: usize,
107 pub original_span: Span<'a>,
109 pub original_line_num: usize,
111}
112
113#[derive(Clone)]
123pub struct PreprocessorState<'a> {
124 pub includes: Vec<&'a Path>,
126 pub defines: Vec<Define<'a>>,
128 pub timescales: Vec<Timescale<'a>>,
130 pub default_nettypes: Vec<(DefaultNettype, Span<'a>)>,
132 pub unconnected_drives: Vec<(UnconnectedDrive, Span<'a>)>,
135 pub cell_defines: Vec<(bool, Span<'a>)>,
137 pub line_directives: Vec<LineDirective<'a>>,
139 pub included_files: HashMap<&'a str, &'a str>,
141 pub curr_standard: StandardVersion,
143 pub errors: Vec<PreprocessorError<'a>>,
145 pub(crate) in_define: bool,
146 pub(crate) in_define_arg: bool,
147 pub(crate) include_depth: usize,
148}
149
150impl<'a> PreprocessorState<'a> {
151 pub fn new(includes: Vec<&'a Path>, defines: Vec<Define<'a>>) -> Self {
153 Self {
154 includes,
155 defines,
156 timescales: vec![],
157 default_nettypes: vec![],
158 unconnected_drives: vec![],
159 cell_defines: vec![],
160 line_directives: vec![],
161 included_files: HashMap::new(),
162 curr_standard: StandardVersion::default(),
163 errors: vec![],
164 in_define: false,
165 in_define_arg: false,
166 include_depth: 0,
167 }
168 }
169 pub fn make_fresh(&mut self, defines: Vec<Define<'a>>) {
173 self.defines = defines;
174 self.timescales = vec![];
175 self.default_nettypes = vec![];
176 self.unconnected_drives = vec![];
177 self.cell_defines = vec![];
178 self.line_directives = vec![];
179 self.curr_standard = StandardVersion::default();
180 self.errors = vec![];
181 self.in_define = false;
182 self.in_define_arg = false;
183 self.include_depth = 0;
184 }
185 pub fn reset_all(&mut self, reset_all_span: Span<'a>) {
189 self.add_timescale(
190 Timescale::new(
191 reset_all_span.clone(),
192 DEFAULT_TIMESCALE.unit,
193 DEFAULT_TIMESCALE.precision,
194 )
195 .unwrap(),
196 );
197 self.add_default_nettype(reset_all_span.clone(), DEFAULT_NETTYPE);
198 self.add_unconnected_drive(
199 reset_all_span.clone(),
200 DEFAULT_UNCONNECTED_DRIVE,
201 );
202 self.add_cell_define(false, reset_all_span);
203 }
204
205 pub fn is_defined(&self, macro_name: &'a str) -> bool {
207 self.defines.iter().any(|d| d.name.0 == macro_name)
208 }
209
210 pub fn get_define_decl(&self, macro_name: &'a str) -> Option<Span<'a>> {
212 match self.defines.iter().find(|d| d.name.0 == macro_name) {
213 None => None,
214 Some(define) => Some(define.name.1.clone()),
215 }
216 }
217
218 #[inline]
223 pub(crate) fn enter_define(&mut self) -> bool {
224 let prev_in_define = self.in_define;
225 self.in_define = true;
226 prev_in_define
227 }
228
229 #[inline]
234 pub(crate) fn exit_define(&mut self, prev_in_define: bool) {
235 self.in_define = prev_in_define;
236 }
237
238 #[inline]
240 pub fn in_define(&self) -> bool {
241 self.in_define
242 }
243
244 #[inline]
249 pub(crate) fn enter_define_arg(&mut self) -> bool {
250 let prev_in_define_arg = self.in_define_arg;
251 self.in_define_arg = true;
252 prev_in_define_arg
253 }
254
255 #[inline]
260 pub(crate) fn exit_define_arg(&mut self, prev_in_define_arg: bool) {
261 self.in_define_arg = prev_in_define_arg;
262 }
263
264 #[inline]
266 pub fn in_define_arg(&self) -> bool {
267 self.in_define_arg
268 }
269
270 pub fn undefine(&mut self, macro_name: &'a str) -> bool {
274 let prev_len = self.defines.len();
275 self.defines.retain(|d| d.name.0 != macro_name);
276 prev_len != self.defines.len()
277 }
278
279 pub fn define(
284 &mut self,
285 macro_name: &'a str,
286 macro_span: Span<'a>,
287 macro_body: DefineBody<'a>,
288 ) {
289 self.defines.push(Define {
290 name: SpannedString(macro_name, macro_span),
291 body: macro_body,
292 });
293 }
294
295 pub fn command_line_define(
300 &mut self,
301 macro_name: &'a str,
302 macro_text: Option<Vec<SpannedToken<'a>>>,
303 ) {
304 self.define(
305 macro_name,
306 Span::default(),
307 match macro_text {
308 None => DefineBody::Empty,
309 Some(token_vec) => DefineBody::Text(token_vec),
310 },
311 )
312 }
313
314 pub fn undefineall(&mut self) {
318 self.defines = vec![];
319 }
320
321 pub fn get_macro_tokens(
324 &self,
325 macro_name: &'a str,
326 ) -> Option<(
327 Span<'a>,
328 (
329 Vec<SpannedToken<'a>>,
330 Option<Vec<(SpannedString<'a>, Option<Vec<SpannedToken<'a>>>)>>,
331 ),
332 )> {
333 for define in &self.defines {
334 if define.name.0 == macro_name {
335 return Some((define.name.1.clone(), define.body.get_tokens()));
336 }
337 }
338 None
339 }
340
341 pub fn get_file_path(&self, include_path: &str) -> Option<PathBuf> {
343 for dir_path in &self.includes {
344 let full_path = Path::new(dir_path).join(include_path);
345 if full_path.exists() {
346 return Some(full_path);
347 }
348 }
349 None
350 }
351
352 pub fn add_timescale(&mut self, timescale: Timescale<'a>) {
356 self.timescales.push(timescale);
357 }
358
359 pub fn get_timescale(&self, span: &Span<'a>) -> &Timescale<'a> {
362 for timescale in self.timescales.iter().rev() {
363 if timescale.is_valid(span) {
364 return timescale;
365 }
366 }
367 &DEFAULT_TIMESCALE
369 }
370
371 pub fn add_default_nettype(
375 &mut self,
376 def_span: Span<'a>,
377 default_nettype: DefaultNettype,
378 ) {
379 self.default_nettypes.push((default_nettype, def_span));
380 }
381
382 pub fn get_default_nettype(&self, span: &Span<'a>) -> &DefaultNettype {
385 for default_nettype in self.default_nettypes.iter().rev() {
386 if default_nettype.1.compare(span) == SpanRelation::Earlier {
387 return &default_nettype.0;
388 }
389 }
390 &DEFAULT_NETTYPE
391 }
392
393 pub(crate) fn retain_include_file(
401 &mut self,
402 include_path: &'a str,
403 include_path_span: Span<'a>,
404 cache: &'a PreprocessorCache<'a>,
405 ) -> Result<(&'a str, &'a str), PreprocessorError<'a>> {
406 let include_path_buf =
407 self.get_file_path(include_path).ok_or_else(|| {
408 PreprocessorError::Include {
409 include_path,
410 include_path_span: include_path_span.clone(),
411 read_err: io::ErrorKind::NotFound,
412 }
413 })?;
414 match self
415 .included_files
416 .get_key_value::<str>(include_path_buf.to_str().unwrap())
417 {
418 Some((path, contents)) => Ok((*path, *contents)),
419 None => {
420 let cached_path = cache.retain_string(
421 include_path_buf.to_str().unwrap().to_owned(),
422 );
423 let file_contents = std::fs::read_to_string(&cached_path)
424 .map_err(|err| PreprocessorError::Include {
425 include_path,
426 include_path_span,
427 read_err: err.kind(),
428 })?;
429 let cached_contents = cache.retain_string(file_contents);
430 self.included_files.insert(cached_path, cached_contents);
431 Ok((cached_path, cached_contents))
432 }
433 }
434 }
435
436 pub fn retain_file(
441 &mut self,
442 file_path: String,
443 file_contents: String,
444 cache: &'a PreprocessorCache<'a>,
445 ) -> (&'a str, &'a str) {
446 match self.included_files.get_key_value::<str>(file_path.as_ref()) {
447 Some((path, contents)) => (*path, *contents),
448 None => {
449 let path = cache.retain_string(file_path);
450 let contents = cache.retain_string(file_contents);
451 self.included_files.insert(path, contents);
452 (path, contents)
453 }
454 }
455 }
456
457 pub fn included_files(&self) -> Vec<(String, String)> {
459 self.included_files
460 .iter()
461 .map(|(a, b)| (a.to_string(), b.to_string()))
462 .collect()
463 }
464
465 pub fn add_unconnected_drive(
470 &mut self,
471 unconnected_drive_span: Span<'a>,
472 unconnected_drive: UnconnectedDrive,
473 ) {
474 self.unconnected_drives
475 .push((unconnected_drive, unconnected_drive_span));
476 }
477
478 pub fn get_unconnected_drive(&self, span: &Span<'a>) -> &UnconnectedDrive {
481 for unconnected_drive in self.unconnected_drives.iter().rev() {
482 if unconnected_drive.1.compare(span) == SpanRelation::Earlier {
483 return &unconnected_drive.0;
484 }
485 }
486 &DEFAULT_UNCONNECTED_DRIVE
487 }
488
489 pub fn add_cell_define(&mut self, is_cell_define: bool, span: Span<'a>) {
493 self.cell_defines.push((is_cell_define, span));
494 }
495
496 pub fn is_cell_module(&self, declaration_span: &Span<'a>) -> bool {
499 for cell_define in self.cell_defines.iter().rev() {
500 if cell_define.1.compare(declaration_span) == SpanRelation::Earlier
501 {
502 return cell_define.0;
503 }
504 }
505 false
506 }
507
508 pub fn add_line_directive(
512 &mut self,
513 file_name: &'a str,
514 line_number: &'a str,
515 dir_span: Span<'a>,
516 ) {
517 let offset = dir_span.bytes.end;
518 let file_contents: &str =
519 self.included_files.get(dir_span.file).unwrap();
520 let line_num = file_contents[..offset].lines().count();
521 let new_line_directive = LineDirective {
522 directive_file_name: file_name,
523 directive_line_number: line_number.parse().unwrap(),
524 original_span: dir_span,
525 original_line_num: line_num,
526 };
527 self.line_directives.push(new_line_directive);
528 }
529
530 pub fn get_line_directive_file(&self, span: &Span<'a>) -> &'a str {
532 let Some(line_directive) = self
533 .line_directives
534 .iter()
535 .rev()
536 .filter(|line_directive| {
537 (line_directive.original_span.file == span.file)
538 && (line_directive.original_span.bytes.start
539 < span.bytes.start) })
541 .next()
542 else {
543 return span.file;
544 };
545 line_directive.directive_file_name
546 }
547
548 pub fn get_line_directive_line(
550 &mut self,
551 span: &Span<'a>,
552 cache: &'a PreprocessorCache<'a>,
553 ) -> &'a str {
554 let offset = span.bytes.end;
555 let file_contents: &str = self.included_files.get(span.file).unwrap();
556 let line_num = file_contents[..offset].lines().count();
557 let Some(line_directive) = self
558 .line_directives
559 .iter()
560 .rev()
561 .filter(|line_directive| {
562 (line_directive.original_span.file == span.file)
563 && (line_directive.original_span.bytes.start
564 < span.bytes.start) })
566 .next()
567 else {
568 return cache.retain_string(line_num.to_string());
569 };
570 let new_line_num = (line_num + line_directive.directive_line_number)
571 - (line_directive.original_line_num + 1);
572 cache.retain_string(new_line_num.to_string())
573 }
574
575 pub(crate) fn get_slice(&self, span: &Span<'a>) -> Option<&'a str> {
577 let file_contents: &str = self.included_files.get(span.file)?;
578 Some(&file_contents[span.bytes.start..span.bytes.end])
579 }
580
581 pub fn retain_string(
582 &mut self,
583 string: String,
584 cache: &'a PreprocessorCache<'a>,
585 ) -> &'a str {
586 cache.retain_string(string)
587 }
588
589 pub fn err(&mut self, warning: PreprocessorError<'a>) {
591 self.errors.push(warning);
592 }
593}