microcad_lang/syntax/source_file/
mod.rs1use crate::{src_ref::*, syntax::*};
7
8#[derive(Clone, Default)]
10pub struct SourceFile {
11 pub name: QualifiedName,
13 pub statements: StatementList,
15 filename: Option<std::path::PathBuf>,
17 pub source: String,
19
20 pub hash: u64,
25}
26
27impl SourceFile {
28 pub fn new(statements: StatementList, source: String, hash: u64) -> Self {
30 Self {
31 statements,
32 source,
33 hash,
34 ..Default::default()
35 }
36 }
37 pub fn filename(&self) -> std::path::PathBuf {
39 self.filename
40 .clone()
41 .unwrap_or(std::path::PathBuf::from(crate::invalid_no_ansi!(SOURCE)))
42 }
43
44 pub fn set_filename(&mut self, path: impl AsRef<std::path::Path>) {
46 assert!(self.filename.is_none());
47 self.filename = Some(path.as_ref().canonicalize().expect("path not found"))
48 }
49
50 pub fn filename_as_str(&self) -> &str {
52 self.filename
53 .as_ref()
54 .map(|f| f.to_str().expect("File name error {filename:?}"))
55 .unwrap_or(crate::invalid!(SOURCE))
56 }
57
58 pub fn id(&self) -> Identifier {
60 self.name.last().unwrap_or(&Identifier::none()).clone()
61 }
62
63 pub fn get_line(&self, line: usize) -> Option<&str> {
67 self.source.lines().nth(line)
68 }
69
70 pub fn num_lines(&self) -> usize {
72 self.source.lines().count()
73 }
74
75 pub fn set_name(&mut self, name: QualifiedName) {
77 self.name = name
78 }
79}
80
81impl std::fmt::Display for SourceFile {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 self.statements.iter().try_for_each(|s| writeln!(f, "{s}"))
84 }
85}
86
87impl std::fmt::Debug for SourceFile {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 self.statements
90 .iter()
91 .try_for_each(|s| writeln!(f, "{s:?}"))
92 }
93}
94
95impl TreeDisplay for SourceFile {
96 fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
97 writeln!(
98 f,
99 "{:depth$}SourceFile '{:?}' ({}):",
100 "",
101 self.id(),
102 self.filename_as_str()
103 )?;
104 depth.indent();
105 self.statements
106 .iter()
107 .try_for_each(|s| s.tree_print(f, depth))
108 }
109}
110
111impl SrcReferrer for SourceFile {
112 fn src_ref(&self) -> crate::src_ref::SrcRef {
113 SrcRef::new(0..self.num_lines(), 0, 0, self.hash)
114 }
115}
116
117#[test]
118fn load_source_file_wrong_location() {
119 let source_file = SourceFile::load("I do not exist.µcad");
120 if let Err(err) = source_file {
121 log::info!("{err}");
122 } else {
124 panic!("Does file exist?");
125 }
126}