ferrum_compiler/syntax/
mod.rs1mod decl;
2pub use decl::*;
3
4mod expr;
5pub use expr::*;
6
7mod node;
8pub use node::*;
9
10mod stmt;
11pub use stmt::*;
12
13mod r#use;
14pub use r#use::*;
15
16mod r#static;
17pub use r#static::*;
18
19use crate::config::Config;
20use crate::log;
21use crate::r#type::FeType;
22use crate::result::Result;
23use crate::token;
24use crate::utils::{fe_from, fe_try_from};
25
26use std::collections::HashMap;
27use std::path::PathBuf;
28use std::sync::{Arc, Mutex};
29
30pub trait SyntaxCompiler<IR> {
31 fn compile_package(cfg: Arc<Config>, entry: Arc<Mutex<FeSyntaxPackage<FeType>>>) -> Result<IR>;
32}
33
34pub trait Resolvable {
35 fn is_signature_resolved(&self) -> bool {
36 return self.is_resolved();
37 }
38
39 fn is_resolved(&self) -> bool;
40}
41
42#[derive(Debug, Clone)]
43pub enum FeSyntaxPackage<T: ResolvedType = ()> {
44 File(FeSyntaxFile<T>),
45 Dir(FeSyntaxDir<T>),
46}
47
48impl From<token::FeTokenPackage> for FeSyntaxPackage {
49 fn from(value: token::FeTokenPackage) -> Self {
50 match value {
51 token::FeTokenPackage::File(file) => return FeSyntaxPackage::File(file.into()),
52 token::FeTokenPackage::Dir(dir) => return FeSyntaxPackage::Dir(dir.into()),
53 };
54 }
55}
56
57impl<T: ResolvedType> From<FeSyntaxPackage<()>> for FeSyntaxPackage<Option<T>> {
58 fn from(value: FeSyntaxPackage<()>) -> Self {
59 match value {
60 FeSyntaxPackage::File(file) => return Self::File(file.into()),
61 FeSyntaxPackage::Dir(dir) => return Self::Dir(dir.into()),
62 }
63 }
64}
65
66impl<T: ResolvedType> Resolvable for FeSyntaxPackage<Option<T>> {
67 fn is_resolved(&self) -> bool {
68 match self {
69 Self::File(file) => return file.is_resolved(),
70 Self::Dir(dir) => return dir.is_resolved(),
71 }
72 }
73}
74
75impl<T: ResolvedType> TryFrom<FeSyntaxPackage<Option<T>>> for FeSyntaxPackage<T> {
76 type Error = FinalizeResolveTypeError;
77
78 fn try_from(value: FeSyntaxPackage<Option<T>>) -> Result<Self, Self::Error> {
79 match value {
80 FeSyntaxPackage::File(file) => {
81 return Ok(FeSyntaxPackage::File(file.try_into()?));
82 }
83 FeSyntaxPackage::Dir(dir) => return Ok(FeSyntaxPackage::Dir(dir.try_into()?)),
84 }
85 }
86}
87
88#[derive(Debug, Clone)]
89pub struct FeSyntaxFile<T: ResolvedType = ()> {
90 pub name: SyntaxPackageName,
91 pub path: PathBuf,
92 pub syntax: Arc<Mutex<SyntaxTree<T>>>,
93}
94
95impl From<token::FeTokenFile> for FeSyntaxFile {
96 fn from(value: token::FeTokenFile) -> Self {
97 return Self {
98 name: value.name.into(),
99 path: value.path,
100 syntax: Arc::new(Mutex::new(SyntaxTree {
101 mods: vec![],
102 uses: vec![],
103 decls: vec![],
104 })),
105 };
106 }
107}
108
109impl<T: ResolvedType> From<FeSyntaxFile<()>> for FeSyntaxFile<Option<T>> {
110 fn from(value: FeSyntaxFile<()>) -> Self {
111 return Self {
112 name: value.name,
113 path: value.path,
114 syntax: fe_from(value.syntax),
115 };
116 }
117}
118
119impl<T: ResolvedType> Resolvable for FeSyntaxFile<Option<T>> {
120 fn is_resolved(&self) -> bool {
121 return self.syntax.lock().unwrap().is_resolved();
122 }
123}
124
125impl<T: ResolvedType> TryFrom<FeSyntaxFile<Option<T>>> for FeSyntaxFile<T> {
126 type Error = FinalizeResolveTypeError;
127
128 fn try_from(value: FeSyntaxFile<Option<T>>) -> Result<Self, Self::Error> {
129 return Ok(Self {
130 name: value.name,
131 path: value.path,
132 syntax: fe_try_from(value.syntax)?,
133 });
134 }
135}
136
137#[derive(Debug, Clone)]
138pub struct FeSyntaxDir<T: ResolvedType = ()> {
139 pub name: SyntaxPackageName,
140 pub path: PathBuf,
141 pub entry_file: FeSyntaxFile<T>,
142 pub local_packages: HashMap<SyntaxPackageName, Arc<Mutex<FeSyntaxPackage<T>>>>,
143}
144
145impl From<token::FeTokenDir> for FeSyntaxDir {
146 fn from(value: token::FeTokenDir) -> Self {
147 return Self {
148 name: value.name.into(),
149 path: value.path,
150 entry_file: value.entry_file.into(),
151 local_packages: value
152 .local_packages
153 .into_iter()
154 .map(|(name, pkg)| (name.into(), fe_from(pkg)))
155 .collect(),
156 };
157 }
158}
159
160impl<T: ResolvedType> From<FeSyntaxDir<()>> for FeSyntaxDir<Option<T>> {
161 fn from(value: FeSyntaxDir<()>) -> Self {
162 let local_packages = value
163 .local_packages
164 .into_iter()
165 .map(|(name, pkg)| (name, fe_from(pkg)))
166 .collect();
167
168 return Self {
169 name: value.name,
170 path: value.path,
171 entry_file: value.entry_file.into(),
172 local_packages,
173 };
174 }
175}
176
177impl<T: ResolvedType> Resolvable for FeSyntaxDir<Option<T>> {
178 fn is_resolved(&self) -> bool {
179 if !self.entry_file.is_resolved() {
180 return log::trace!(false);
181 }
182
183 for pkg in self.local_packages.values() {
184 if !pkg.lock().unwrap().is_resolved() {
185 return log::trace!(false);
186 }
187 }
188
189 return true;
190 }
191}
192
193impl<T: ResolvedType> TryFrom<FeSyntaxDir<Option<T>>> for FeSyntaxDir<T> {
194 type Error = FinalizeResolveTypeError;
195
196 fn try_from(value: FeSyntaxDir<Option<T>>) -> Result<Self, Self::Error> {
197 let local_packages = value
198 .local_packages
199 .into_iter()
200 .map(|(name, pkg)| Ok((name, fe_try_from(pkg)?)))
201 .collect::<Result<
202 HashMap<SyntaxPackageName, Arc<Mutex<FeSyntaxPackage<T>>>>,
203 FinalizeResolveTypeError,
204 >>()?;
205
206 return Ok(FeSyntaxDir {
207 name: value.name,
208 path: value.path,
209 entry_file: value.entry_file.try_into()?,
210 local_packages,
211 });
212 }
213}
214
215#[derive(Debug, Clone, Hash, PartialEq, Eq)]
216pub struct SyntaxPackageName(pub Arc<str>);
217
218impl From<token::TokenPackageName> for SyntaxPackageName {
219 fn from(value: token::TokenPackageName) -> Self {
220 return Self(value.0);
221 }
222}
223
224#[derive(Debug, Clone)]
225pub struct SyntaxTree<T: ResolvedType = ()> {
226 pub mods: Vec<Mod>,
227 pub uses: Vec<Arc<Mutex<Use<T>>>>,
228 pub decls: Vec<Arc<Mutex<Decl<T>>>>,
229}
230
231impl<T: ResolvedType> From<SyntaxTree<()>> for SyntaxTree<Option<T>> {
232 fn from(value: SyntaxTree<()>) -> Self {
233 return Self {
234 mods: value.mods,
235 uses: value.uses.into_iter().map(fe_from).collect(),
236 decls: value.decls.into_iter().map(fe_from).collect(),
237 };
238 }
239}
240
241impl<T: ResolvedType> Resolvable for SyntaxTree<Option<T>> {
242 fn is_resolved(&self) -> bool {
243 for u in &self.uses {
244 if !u.lock().unwrap().is_resolved() {
245 return log::trace!(false);
246 }
247 }
248
249 for d in &self.decls {
250 if !d.lock().unwrap().is_resolved() {
251 return log::trace!(false);
252 }
253 }
254
255 return true;
256 }
257}
258
259impl<T: ResolvedType> TryFrom<SyntaxTree<Option<T>>> for SyntaxTree<T> {
260 type Error = FinalizeResolveTypeError;
261
262 fn try_from(value: SyntaxTree<Option<T>>) -> Result<Self, Self::Error> {
263 return Ok(Self {
264 mods: value.mods,
265 uses: value
266 .uses
267 .into_iter()
268 .map(fe_try_from)
269 .collect::<Result<Vec<Arc<Mutex<Use<T>>>>, Self::Error>>()?,
270 decls: value
271 .decls
272 .into_iter()
273 .map(fe_try_from)
274 .collect::<Result<Vec<Arc<Mutex<Decl<T>>>>, Self::Error>>()?,
275 });
276 }
277}
278
279#[derive(Debug, Clone, PartialEq)]
280pub struct Mod(pub Arc<str>);
281
282#[derive(Debug, Clone)]
283pub struct FinalizeResolveTypeError {
284 pub file: &'static str,
285 pub line: u32,
286}
287
288impl std::fmt::Display for FinalizeResolveTypeError {
289 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
290 return write!(f, "{self:?}");
291 }
292}
293impl std::error::Error for FinalizeResolveTypeError {}
294
295pub trait ResolvedType: std::fmt::Debug + Clone + PartialEq {}
296impl ResolvedType for () {}
297impl ResolvedType for FeType {}
298impl<T: ResolvedType> ResolvedType for Option<T> {}
299
300pub trait IsTerminal<T: ResolvedType> {
301 fn is_terminal(&mut self) -> bool {
302 return false;
303 }
304}