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<(
56 SpannedString<'a>,
57 Option<(
58 Span<'a>, Vec<SpannedToken<'a>>,
60 )>,
61 )>,
62 pub body: Option<Vec<SpannedToken<'a>>>,
64}
65
66impl<'a> DefineBody<'a> {
67 pub fn get_tokens(
73 &self,
74 ) -> (
75 Vec<SpannedToken<'a>>,
76 Option<Vec<(SpannedString<'a>, Option<Vec<SpannedToken<'a>>>)>>,
77 ) {
78 match self {
79 DefineBody::Empty => (vec![], None),
80 DefineBody::Text(token_vec) => (token_vec.clone(), None),
81 DefineBody::Function(def_func) => {
82 let function_args = def_func
83 .args
84 .iter()
85 .map(|(a, b)| match b {
86 Some((_, tokens)) => (a.clone(), Some(tokens.clone())),
87 None => (a.clone(), None),
88 })
89 .collect();
90 match &def_func.body {
91 Some(token_vec) => (token_vec.clone(), Some(function_args)),
92 None => (vec![], Some(function_args)),
93 }
94 }
95 }
96 }
97}
98
99#[derive(Clone)]
101pub struct LineDirective<'a> {
102 pub directive_file_name: &'a str,
104 pub directive_line_number: usize,
106 pub original_span: Span<'a>,
108 pub original_line_num: usize,
110}
111
112#[derive(Clone)]
122pub struct PreprocessorState<'a> {
123 pub includes: Vec<&'a Path>,
125 pub defines: Vec<Define<'a>>,
127 pub timescales: Vec<Timescale<'a>>,
129 pub default_nettypes: Vec<(DefaultNettype, Span<'a>)>,
131 pub unconnected_drives: Vec<(UnconnectedDrive, Span<'a>)>,
134 pub cell_defines: Vec<(bool, Span<'a>)>,
136 pub line_directives: Vec<LineDirective<'a>>,
138 pub included_files: HashMap<&'a str, &'a str>,
140 pub curr_standard: StandardVersion,
142 pub warnings: Vec<PreprocessorWarning<'a>>,
144 pub(crate) in_define: bool,
145 pub(crate) in_define_arg: bool,
146 pub(crate) include_history: Vec<Span<'a>>,
147}
148
149impl<'a> PreprocessorState<'a> {
150 pub fn new(includes: Vec<&'a Path>, defines: Vec<Define<'a>>) -> Self {
152 Self {
153 includes,
154 defines,
155 timescales: vec![],
156 default_nettypes: vec![],
157 unconnected_drives: vec![],
158 cell_defines: vec![],
159 line_directives: vec![],
160 included_files: HashMap::new(),
161 curr_standard: StandardVersion::default(),
162 warnings: vec![],
163 in_define: false,
164 in_define_arg: false,
165 include_history: vec![],
166 }
167 }
168 pub fn make_fresh(&mut self, defines: Vec<Define<'a>>) {
172 self.defines = defines;
173 self.timescales = vec![];
174 self.default_nettypes = vec![];
175 self.unconnected_drives = vec![];
176 self.cell_defines = vec![];
177 self.line_directives = vec![];
178 self.curr_standard = StandardVersion::default();
179 self.warnings = vec![];
180 self.in_define = false;
181 self.in_define_arg = false;
182 self.include_history = vec![];
183 }
184 pub fn reset_all(&mut self, reset_all_span: Span<'a>) {
188 self.add_timescale(
189 Timescale::new(
190 reset_all_span.clone(),
191 DEFAULT_TIMESCALE.unit,
192 DEFAULT_TIMESCALE.precision,
193 )
194 .unwrap(),
195 );
196 self.add_default_nettype(reset_all_span.clone(), DEFAULT_NETTYPE);
197 self.add_unconnected_drive(
198 reset_all_span.clone(),
199 DEFAULT_UNCONNECTED_DRIVE,
200 );
201 self.add_cell_define(false, reset_all_span);
202 }
203
204 pub fn is_defined(&self, macro_name: &'a str) -> bool {
206 self.defines.iter().any(|d| d.name.0 == macro_name)
207 }
208
209 pub fn get_define_decl(&self, macro_name: &'a str) -> Option<Span<'a>> {
211 match self.defines.iter().find(|d| d.name.0 == macro_name) {
212 None => None,
213 Some(define) => Some(define.name.1.clone()),
214 }
215 }
216
217 #[inline]
222 pub(crate) fn enter_define(&mut self) -> bool {
223 let prev_in_define = self.in_define;
224 self.in_define = true;
225 prev_in_define
226 }
227
228 #[inline]
233 pub(crate) fn exit_define(&mut self, prev_in_define: bool) {
234 self.in_define = prev_in_define;
235 }
236
237 #[inline]
239 pub fn in_define(&self) -> bool {
240 self.in_define
241 }
242
243 #[inline]
248 pub(crate) fn enter_define_arg(&mut self) -> bool {
249 let prev_in_define_arg = self.in_define_arg;
250 self.in_define_arg = true;
251 prev_in_define_arg
252 }
253
254 #[inline]
259 pub(crate) fn exit_define_arg(&mut self, prev_in_define_arg: bool) {
260 self.in_define_arg = prev_in_define_arg;
261 }
262
263 #[inline]
265 pub fn in_define_arg(&self) -> bool {
266 self.in_define_arg
267 }
268
269 pub fn undefine(&mut self, macro_name: &'a str) -> bool {
273 let prev_len = self.defines.len();
274 self.defines.retain(|d| d.name.0 != macro_name);
275 prev_len != self.defines.len()
276 }
277
278 pub fn define(
283 &mut self,
284 macro_name: &'a str,
285 macro_span: Span<'a>,
286 macro_body: DefineBody<'a>,
287 ) {
288 self.defines.push(Define {
289 name: SpannedString(macro_name, macro_span),
290 body: macro_body,
291 });
292 }
293
294 pub fn command_line_define(
299 &mut self,
300 macro_name: &'a str,
301 macro_text: Option<Vec<SpannedToken<'a>>>,
302 ) {
303 self.define(
304 macro_name,
305 Span::default(),
306 match macro_text {
307 None => DefineBody::Empty,
308 Some(token_vec) => DefineBody::Text(token_vec),
309 },
310 )
311 }
312
313 pub fn undefineall(&mut self) {
317 self.defines = vec![];
318 }
319
320 pub fn get_macro_tokens(
323 &self,
324 macro_name: &'a str,
325 ) -> Option<(
326 Span<'a>,
327 (
328 Vec<SpannedToken<'a>>,
329 Option<Vec<(SpannedString<'a>, Option<Vec<SpannedToken<'a>>>)>>,
330 ),
331 )> {
332 for define in &self.defines {
333 if define.name.0 == macro_name {
334 return Some((define.name.1.clone(), define.body.get_tokens()));
335 }
336 }
337 None
338 }
339
340 pub fn get_file_path(&self, include_path: &str) -> Option<PathBuf> {
342 for dir_path in &self.includes {
343 let full_path = Path::new(dir_path).join(include_path);
344 if full_path.exists() {
345 return Some(full_path);
346 }
347 }
348 Some(PathBuf::from(include_path))
349 }
350
351 pub fn add_timescale(&mut self, timescale: Timescale<'a>) {
355 self.timescales.push(timescale);
356 }
357
358 pub fn get_timescale(&self, span: &Span<'a>) -> &Timescale<'a> {
361 for timescale in self.timescales.iter().rev() {
362 if timescale.is_valid(span) {
363 return timescale;
364 }
365 }
366 &DEFAULT_TIMESCALE
368 }
369
370 pub fn add_default_nettype(
374 &mut self,
375 def_span: Span<'a>,
376 default_nettype: DefaultNettype,
377 ) {
378 self.default_nettypes.push((default_nettype, def_span));
379 }
380
381 pub fn get_default_nettype(&self, span: &Span<'a>) -> &DefaultNettype {
384 for default_nettype in self.default_nettypes.iter().rev() {
385 if default_nettype.1.compare(span) == SpanRelation::Earlier {
386 return &default_nettype.0;
387 }
388 }
389 &DEFAULT_NETTYPE
390 }
391
392 pub(crate) fn retain_include_file(
400 &mut self,
401 include_path: &'a str,
402 include_path_span: Span<'a>,
403 cache: &'a PreprocessorCache<'a>,
404 ) -> Result<(&'a str, &'a str), PreprocessorError<'a>> {
405 let include_path_buf =
406 self.get_file_path(include_path).ok_or_else(|| {
407 PreprocessorError::Include(
408 include_path_span.clone(),
409 include_path.to_string(),
410 io::Error::new(io::ErrorKind::NotFound, "File not found"),
411 )
412 })?;
413 match self
414 .included_files
415 .get_key_value::<str>(include_path_buf.to_str().unwrap())
416 {
417 Some((path, contents)) => Ok((*path, *contents)),
418 None => {
419 let cached_path = cache.retain_string(
420 include_path_buf.to_str().unwrap().to_owned(),
421 );
422 let file_contents = std::fs::read_to_string(&cached_path)
423 .map_err(|err| {
424 PreprocessorError::Include(
425 include_path_span,
426 include_path.to_string(),
427 err,
428 )
429 })?;
430 let cached_contents = cache.retain_string(file_contents);
431 self.included_files.insert(cached_path, cached_contents);
432 Ok((cached_path, cached_contents))
433 }
434 }
435 }
436
437 pub fn retain_file(
442 &mut self,
443 file_path: String,
444 file_contents: String,
445 cache: &'a PreprocessorCache<'a>,
446 ) -> (&'a str, &'a str) {
447 match self.included_files.get_key_value::<str>(file_path.as_ref()) {
448 Some((path, contents)) => (*path, *contents),
449 None => {
450 let path = cache.retain_string(file_path);
451 let contents = cache.retain_string(file_contents);
452 self.included_files.insert(path, contents);
453 (path, contents)
454 }
455 }
456 }
457
458 pub fn included_files(&self) -> Vec<(String, String)> {
460 self.included_files
461 .iter()
462 .map(|(a, b)| (a.to_string(), b.to_string()))
463 .collect()
464 }
465
466 pub fn add_unconnected_drive(
471 &mut self,
472 unconnected_drive_span: Span<'a>,
473 unconnected_drive: UnconnectedDrive,
474 ) {
475 self.unconnected_drives
476 .push((unconnected_drive, unconnected_drive_span));
477 }
478
479 pub fn get_unconnected_drive(&self, span: &Span<'a>) -> &UnconnectedDrive {
482 for unconnected_drive in self.unconnected_drives.iter().rev() {
483 if unconnected_drive.1.compare(span) == SpanRelation::Earlier {
484 return &unconnected_drive.0;
485 }
486 }
487 &DEFAULT_UNCONNECTED_DRIVE
488 }
489
490 pub fn add_cell_define(&mut self, is_cell_define: bool, span: Span<'a>) {
494 self.cell_defines.push((is_cell_define, span));
495 }
496
497 pub fn is_cell_module(&self, declaration_span: &Span<'a>) -> bool {
500 for cell_define in self.cell_defines.iter().rev() {
501 if cell_define.1.compare(declaration_span) == SpanRelation::Earlier
502 {
503 return cell_define.0;
504 }
505 }
506 false
507 }
508
509 pub fn add_line_directive(
513 &mut self,
514 file_name: &'a str,
515 line_number: &'a str,
516 dir_span: Span<'a>,
517 ) {
518 let offset = dir_span.bytes.end;
519 let file_contents: &str =
520 self.included_files.get(dir_span.file).unwrap();
521 let line_num = file_contents[..offset].lines().count();
522 let new_line_directive = LineDirective {
523 directive_file_name: file_name,
524 directive_line_number: line_number.parse().unwrap(),
525 original_span: dir_span,
526 original_line_num: line_num,
527 };
528 self.line_directives.push(new_line_directive);
529 }
530
531 pub fn get_line_directive_file(&self, span: &Span<'a>) -> &'a str {
533 let Some(line_directive) = self
534 .line_directives
535 .iter()
536 .rev()
537 .filter(|line_directive| {
538 (line_directive.original_span.file == span.file)
539 && (line_directive.original_span.bytes.start
540 < span.bytes.start) })
542 .next()
543 else {
544 return span.file;
545 };
546 line_directive.directive_file_name
547 }
548
549 pub fn get_line_directive_line(
551 &mut self,
552 span: &Span<'a>,
553 cache: &'a PreprocessorCache<'a>,
554 ) -> &'a str {
555 let offset = span.bytes.end;
556 let file_contents: &str = self.included_files.get(span.file).unwrap();
557 let line_num = file_contents[..offset].lines().count();
558 let Some(line_directive) = self
559 .line_directives
560 .iter()
561 .rev()
562 .filter(|line_directive| {
563 (line_directive.original_span.file == span.file)
564 && (line_directive.original_span.bytes.start
565 < span.bytes.start) })
567 .next()
568 else {
569 return cache.retain_string(line_num.to_string());
570 };
571 let new_line_num = (line_num + line_directive.directive_line_number)
572 - (line_directive.original_line_num + 1);
573 cache.retain_string(new_line_num.to_string())
574 }
575
576 pub(crate) fn get_slice(&self, span: &Span<'a>) -> Option<&'a str> {
578 let file_contents: &str = self.included_files.get(span.file)?;
579 Some(&file_contents[span.bytes.start..span.bytes.end])
580 }
581
582 pub fn retain_string(
583 &mut self,
584 string: String,
585 cache: &'a PreprocessorCache<'a>,
586 ) -> &'a str {
587 cache.retain_string(string)
588 }
589
590 pub fn warn(&mut self, warning: PreprocessorWarning<'a>) {
592 self.warnings.push(warning);
593 }
594}