1use crate::*;
7use forj_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
38impl<'a> From<&'a str> for Define<'a> {
39 fn from(value: &'a str) -> Self {
40 let mut components = value.splitn(2, "=");
41 let name = SpannedString(components.next().unwrap(), Span::default());
42 let body = match components.next() {
43 Some(text) => DefineBody::Text(lex(text, "").tokens().collect()),
44 None => DefineBody::Empty,
45 };
46 Self { name, body }
47 }
48}
49
50#[derive(Clone, Debug)]
57pub enum DefineBody<'a> {
58 Empty,
59 Text(Vec<SpannedToken<'a>>),
60 Function(DefineFunction<'a>),
61}
62
63#[derive(Clone, Debug)]
65pub struct DefineFunction<'a> {
66 pub args: Vec<(
69 SpannedString<'a>,
70 Option<(
71 Span<'a>, Vec<SpannedToken<'a>>,
73 )>,
74 )>,
75 pub body: Option<Vec<SpannedToken<'a>>>,
77}
78
79impl<'a> DefineBody<'a> {
80 pub fn get_tokens(
86 &self,
87 ) -> (
88 Vec<SpannedToken<'a>>,
89 Option<Vec<(SpannedString<'a>, Option<Vec<SpannedToken<'a>>>)>>,
90 ) {
91 match self {
92 DefineBody::Empty => (vec![], None),
93 DefineBody::Text(token_vec) => (token_vec.clone(), None),
94 DefineBody::Function(def_func) => {
95 let function_args = def_func
96 .args
97 .iter()
98 .map(|(a, b)| match b {
99 Some((_, tokens)) => (a.clone(), Some(tokens.clone())),
100 None => (a.clone(), None),
101 })
102 .collect();
103 match &def_func.body {
104 Some(token_vec) => (token_vec.clone(), Some(function_args)),
105 None => (vec![], Some(function_args)),
106 }
107 }
108 }
109 }
110}
111
112#[derive(Clone)]
114pub struct LineDirective<'a> {
115 pub directive_file_name: &'a str,
117 pub directive_line_number: usize,
119 pub original_span: Span<'a>,
121 pub original_line_num: usize,
123}
124
125#[derive(Clone)]
135pub struct PreprocessorState<'a> {
136 pub includes: Vec<&'a Path>,
138 pub defines: Vec<Define<'a>>,
140 pub timescales: Vec<Timescale<'a>>,
142 pub default_nettypes: Vec<(DefaultNettype, Span<'a>)>,
144 pub unconnected_drives: Vec<(UnconnectedDrive, Span<'a>)>,
147 pub cell_defines: Vec<(bool, Span<'a>)>,
149 pub line_directives: Vec<LineDirective<'a>>,
151 pub included_files: HashMap<&'a str, &'a str>,
153 pub curr_standard: StandardVersion,
155 pub errors: Vec<PreprocessorError<'a>>,
157 pub(crate) in_define: bool,
158 pub(crate) in_define_arg: bool,
159 pub(crate) in_text_macro_arg: bool,
160 pub(crate) include_depth: usize,
161}
162
163impl<'a> PreprocessorState<'a> {
164 pub fn new(includes: Vec<&'a Path>, defines: Vec<Define<'a>>) -> Self {
166 Self {
167 includes,
168 defines,
169 timescales: vec![],
170 default_nettypes: vec![],
171 unconnected_drives: vec![],
172 cell_defines: vec![],
173 line_directives: vec![],
174 included_files: HashMap::new(),
175 curr_standard: StandardVersion::default(),
176 errors: vec![],
177 in_define: false,
178 in_define_arg: false,
179 in_text_macro_arg: false,
180 include_depth: 0,
181 }
182 }
183 pub fn make_fresh(&mut self, defines: Vec<Define<'a>>) {
187 self.defines = defines;
188 self.timescales = vec![];
189 self.default_nettypes = vec![];
190 self.unconnected_drives = vec![];
191 self.cell_defines = vec![];
192 self.line_directives = vec![];
193 self.curr_standard = StandardVersion::default();
194 self.errors = vec![];
195 self.in_define = false;
196 self.in_define_arg = false;
197 self.include_depth = 0;
198 }
199 pub fn reset_all(&mut self, reset_all_span: Span<'a>) {
203 self.add_timescale(
204 Timescale::new(
205 reset_all_span.clone(),
206 DEFAULT_TIMESCALE.unit,
207 DEFAULT_TIMESCALE.precision,
208 )
209 .unwrap(),
210 );
211 self.add_default_nettype(reset_all_span.clone(), DEFAULT_NETTYPE);
212 self.add_unconnected_drive(
213 reset_all_span.clone(),
214 DEFAULT_UNCONNECTED_DRIVE,
215 );
216 self.add_cell_define(false, reset_all_span);
217 }
218
219 pub fn is_defined(&self, macro_name: &'a str) -> bool {
221 self.defines.iter().any(|d| d.name.0 == macro_name)
222 }
223
224 pub fn get_define_decl(&self, macro_name: &'a str) -> Option<Span<'a>> {
226 match self.defines.iter().find(|d| d.name.0 == macro_name) {
227 None => None,
228 Some(define) => Some(define.name.1.clone()),
229 }
230 }
231
232 #[inline]
237 pub(crate) fn enter_define(&mut self) -> bool {
238 let prev_in_define = self.in_define;
239 self.in_define = true;
240 prev_in_define
241 }
242
243 #[inline]
248 pub(crate) fn exit_define(&mut self, prev_in_define: bool) {
249 self.in_define = prev_in_define;
250 }
251
252 #[inline]
254 pub fn in_define(&self) -> bool {
255 self.in_define
256 }
257
258 #[inline]
263 pub(crate) fn enter_define_arg(&mut self) -> bool {
264 let prev_in_define_arg = self.in_define_arg;
265 self.in_define_arg = true;
266 prev_in_define_arg
267 }
268
269 #[inline]
274 pub(crate) fn exit_define_arg(&mut self, prev_in_define_arg: bool) {
275 self.in_define_arg = prev_in_define_arg;
276 }
277
278 #[inline]
280 pub fn in_define_arg(&self) -> bool {
281 self.in_define_arg
282 }
283
284 #[inline]
289 pub(crate) fn enter_text_macro_arg(&mut self) -> bool {
290 let prev_in_text_macro_arg = self.in_text_macro_arg;
291 self.in_text_macro_arg = true;
292 prev_in_text_macro_arg
293 }
294
295 #[inline]
300 pub(crate) fn exit_text_macro_arg(&mut self, prev_in_text_macro_arg: bool) {
301 self.in_text_macro_arg = prev_in_text_macro_arg;
302 }
303
304 #[inline]
306 pub fn in_text_macro_arg(&self) -> bool {
307 self.in_text_macro_arg
308 }
309
310 pub fn undefine(&mut self, macro_name: &'a str) -> bool {
314 let prev_len = self.defines.len();
315 self.defines.retain(|d| d.name.0 != macro_name);
316 prev_len != self.defines.len()
317 }
318
319 pub fn define(
324 &mut self,
325 macro_name: &'a str,
326 macro_span: Span<'a>,
327 macro_body: DefineBody<'a>,
328 ) {
329 self.defines.push(Define {
330 name: SpannedString(macro_name, macro_span),
331 body: macro_body,
332 });
333 }
334
335 pub fn command_line_define(
340 &mut self,
341 macro_name: &'a str,
342 macro_text: Option<Vec<SpannedToken<'a>>>,
343 ) {
344 self.define(
345 macro_name,
346 Span::default(),
347 match macro_text {
348 None => DefineBody::Empty,
349 Some(token_vec) => DefineBody::Text(token_vec),
350 },
351 )
352 }
353
354 pub fn undefineall(&mut self) {
358 self.defines = vec![];
359 }
360
361 pub fn get_macro_tokens(
364 &self,
365 macro_name: &'a str,
366 ) -> Option<(
367 Span<'a>,
368 (
369 Vec<SpannedToken<'a>>,
370 Option<Vec<(SpannedString<'a>, Option<Vec<SpannedToken<'a>>>)>>,
371 ),
372 )> {
373 for define in &self.defines {
374 if define.name.0 == macro_name {
375 return Some((define.name.1.clone(), define.body.get_tokens()));
376 }
377 }
378 None
379 }
380
381 pub fn get_file_path(&self, include_path: &str) -> Option<PathBuf> {
383 for dir_path in &self.includes {
384 let full_path = Path::new(dir_path).join(include_path);
385 if full_path.exists() {
386 return Some(full_path);
387 }
388 }
389 None
390 }
391
392 pub fn add_timescale(&mut self, timescale: Timescale<'a>) {
396 self.timescales.push(timescale);
397 }
398
399 pub fn get_timescale(&self, span: &Span<'a>) -> &Timescale<'a> {
402 for timescale in self.timescales.iter().rev() {
403 if timescale.is_valid(span) {
404 return timescale;
405 }
406 }
407 &DEFAULT_TIMESCALE
409 }
410
411 pub fn add_default_nettype(
415 &mut self,
416 def_span: Span<'a>,
417 default_nettype: DefaultNettype,
418 ) {
419 self.default_nettypes.push((default_nettype, def_span));
420 }
421
422 pub fn get_default_nettype(&self, span: &Span<'a>) -> &DefaultNettype {
425 for default_nettype in self.default_nettypes.iter().rev() {
426 if default_nettype.1.compare(span) == SpanRelation::Earlier {
427 return &default_nettype.0;
428 }
429 }
430 &DEFAULT_NETTYPE
431 }
432
433 pub(crate) fn retain_include_file(
441 &mut self,
442 include_path: &'a str,
443 include_path_span: Span<'a>,
444 cache: &'a PreprocessorCache<'a>,
445 ) -> Result<(&'a str, &'a str), PreprocessorError<'a>> {
446 let include_path_buf =
447 self.get_file_path(include_path).ok_or_else(|| {
448 PreprocessorError::Include {
449 include_path,
450 include_path_span: include_path_span.clone(),
451 read_err: io::ErrorKind::NotFound,
452 }
453 })?;
454 match self
455 .included_files
456 .get_key_value::<str>(include_path_buf.to_str().unwrap())
457 {
458 Some((path, contents)) => Ok((*path, *contents)),
459 None => {
460 let cached_path = cache.retain_string(
461 include_path_buf.to_str().unwrap().to_owned(),
462 );
463 let file_contents = std::fs::read_to_string(&cached_path)
464 .map_err(|err| PreprocessorError::Include {
465 include_path,
466 include_path_span,
467 read_err: err.kind(),
468 })?;
469 let cached_contents = cache.retain_string(file_contents);
470 self.included_files.insert(cached_path, cached_contents);
471 Ok((cached_path, cached_contents))
472 }
473 }
474 }
475
476 pub fn retain_file(
481 &mut self,
482 file_path: String,
483 file_contents: String,
484 cache: &'a PreprocessorCache<'a>,
485 ) -> (&'a str, &'a str) {
486 match self.included_files.get_key_value::<str>(file_path.as_ref()) {
487 Some((path, contents)) => (*path, *contents),
488 None => {
489 let path = cache.retain_string(file_path);
490 let contents = cache.retain_string(file_contents);
491 self.included_files.insert(path, contents);
492 (path, contents)
493 }
494 }
495 }
496
497 pub fn included_files(&self) -> Vec<(String, String)> {
499 self.included_files
500 .iter()
501 .map(|(a, b)| (a.to_string(), b.to_string()))
502 .collect()
503 }
504
505 pub fn add_unconnected_drive(
510 &mut self,
511 unconnected_drive_span: Span<'a>,
512 unconnected_drive: UnconnectedDrive,
513 ) {
514 self.unconnected_drives
515 .push((unconnected_drive, unconnected_drive_span));
516 }
517
518 pub fn get_unconnected_drive(&self, span: &Span<'a>) -> &UnconnectedDrive {
521 for unconnected_drive in self.unconnected_drives.iter().rev() {
522 if unconnected_drive.1.compare(span) == SpanRelation::Earlier {
523 return &unconnected_drive.0;
524 }
525 }
526 &DEFAULT_UNCONNECTED_DRIVE
527 }
528
529 pub fn add_cell_define(&mut self, is_cell_define: bool, span: Span<'a>) {
533 self.cell_defines.push((is_cell_define, span));
534 }
535
536 pub fn is_cell_module(&self, declaration_span: &Span<'a>) -> bool {
539 for cell_define in self.cell_defines.iter().rev() {
540 if cell_define.1.compare(declaration_span) == SpanRelation::Earlier
541 {
542 return cell_define.0;
543 }
544 }
545 false
546 }
547
548 pub fn add_line_directive(
552 &mut self,
553 file_name: &'a str,
554 line_number: &'a str,
555 dir_span: Span<'a>,
556 ) {
557 let offset = dir_span.bytes.end;
558 let file_contents: &str =
559 self.included_files.get(dir_span.file).unwrap();
560 let line_num = file_contents[..offset].lines().count();
561 let new_line_directive = LineDirective {
562 directive_file_name: file_name,
563 directive_line_number: line_number.parse().unwrap(),
564 original_span: dir_span,
565 original_line_num: line_num,
566 };
567 self.line_directives.push(new_line_directive);
568 }
569
570 pub fn get_line_directive_file(&self, span: &Span<'a>) -> &'a str {
572 let Some(line_directive) = self
573 .line_directives
574 .iter()
575 .rev()
576 .filter(|line_directive| {
577 (line_directive.original_span.file == span.file)
578 && (line_directive.original_span.bytes.start
579 < span.bytes.start) })
581 .next()
582 else {
583 return span.file;
584 };
585 line_directive.directive_file_name
586 }
587
588 pub fn get_line_directive_line(
590 &mut self,
591 span: &Span<'a>,
592 cache: &'a PreprocessorCache<'a>,
593 ) -> &'a str {
594 let offset = span.bytes.end;
595 let file_contents: &str = self.included_files.get(span.file).unwrap();
596 let line_num = file_contents[..offset].lines().count();
597 let Some(line_directive) = self
598 .line_directives
599 .iter()
600 .rev()
601 .filter(|line_directive| {
602 (line_directive.original_span.file == span.file)
603 && (line_directive.original_span.bytes.start
604 < span.bytes.start) })
606 .next()
607 else {
608 return cache.retain_string(line_num.to_string());
609 };
610 let new_line_num = (line_num + line_directive.directive_line_number)
611 - (line_directive.original_line_num + 1);
612 cache.retain_string(new_line_num.to_string())
613 }
614
615 pub(crate) fn get_slice(&self, span: &Span<'a>) -> Option<&'a str> {
617 let file_contents: &str = self.included_files.get(span.file)?;
618 Some(&file_contents[span.bytes.start..span.bytes.end])
619 }
620
621 pub fn retain_string(
622 &mut self,
623 string: String,
624 cache: &'a PreprocessorCache<'a>,
625 ) -> &'a str {
626 cache.retain_string(string)
627 }
628
629 pub fn err(&mut self, warning: PreprocessorError<'a>) {
631 self.errors.push(warning);
632 }
633}