ee89d2330d
This commit introduces support for comments within the AST nodes. Comments are now parsed by the lexer and stored within the `Token` struct. These comments are then propagated through various compiler phases, including the `Node` struct, ensuring they are preserved in the Abstract Syntax Tree. This change enhances the AST's ability to retain source code information, which can be valuable for debugging and analysis.
108 lines
3.3 KiB
Rust
108 lines
3.3 KiB
Rust
use crate::ast::nodes::{
|
|
Address, AnalyzedNode, IdentifierBinding, Node, NodeKind, NodeMetrics,
|
|
};
|
|
use crate::ast::types::{Purity, RecordLayout, StaticType, Value};
|
|
use std::cell::RefCell;
|
|
use std::rc::Rc;
|
|
|
|
pub struct Folder<'a> {
|
|
pub globals: &'a Option<Rc<RefCell<Vec<Value>>>>,
|
|
}
|
|
|
|
impl<'a> Folder<'a> {
|
|
pub fn new(globals: &'a Option<Rc<RefCell<Vec<Value>>>>) -> Self {
|
|
Self { globals }
|
|
}
|
|
|
|
pub fn make_constant_node(&self, val: Value, template: &AnalyzedNode) -> AnalyzedNode {
|
|
let ty = val.static_type();
|
|
let typed_original = Rc::new(Node {
|
|
identity: template.identity.clone(),
|
|
kind: NodeKind::Constant(val.clone()),
|
|
comments: template.comments.clone(),
|
|
ty: ty.clone(),
|
|
});
|
|
Node {
|
|
identity: template.identity.clone(),
|
|
kind: NodeKind::Constant(val),
|
|
comments: template.comments.clone(),
|
|
ty: NodeMetrics {
|
|
original: typed_original,
|
|
purity: Purity::Pure,
|
|
is_recursive: false,
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn make_nop_node(&self, template: &AnalyzedNode) -> AnalyzedNode {
|
|
let typed_original = Rc::new(Node {
|
|
identity: template.identity.clone(),
|
|
kind: NodeKind::Nop,
|
|
comments: template.comments.clone(),
|
|
ty: StaticType::Void,
|
|
});
|
|
Node {
|
|
identity: template.identity.clone(),
|
|
kind: NodeKind::Nop,
|
|
comments: template.comments.clone(),
|
|
ty: NodeMetrics {
|
|
original: typed_original,
|
|
purity: Purity::Pure,
|
|
is_recursive: false,
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn try_fold_record(
|
|
&self,
|
|
layout: &std::sync::Arc<RecordLayout>,
|
|
values: &[Rc<AnalyzedNode>],
|
|
template: &AnalyzedNode,
|
|
) -> Option<AnalyzedNode> {
|
|
let mut constant_values = Vec::with_capacity(values.len());
|
|
|
|
for v_node in values {
|
|
if let NodeKind::Constant(val) = &v_node.kind {
|
|
constant_values.push(val.clone());
|
|
} else {
|
|
return None;
|
|
}
|
|
}
|
|
|
|
let record_val = Value::Record(layout.clone(), Rc::new(constant_values));
|
|
Some(self.make_constant_node(record_val, template))
|
|
}
|
|
|
|
pub fn try_fold_pure(
|
|
&self,
|
|
callee: &AnalyzedNode,
|
|
arg_nodes: &[Rc<AnalyzedNode>],
|
|
) -> Option<AnalyzedNode> {
|
|
if callee.ty.purity < Purity::Pure {
|
|
return None;
|
|
}
|
|
|
|
let mut arg_values = Vec::with_capacity(arg_nodes.len());
|
|
for node in arg_nodes {
|
|
if let NodeKind::Constant(val) = &node.kind {
|
|
arg_values.push(val.clone());
|
|
} else {
|
|
return None;
|
|
}
|
|
}
|
|
let func_val = match &callee.kind {
|
|
NodeKind::Identifier {
|
|
binding: IdentifierBinding::Reference(Address::Global(idx)),
|
|
..
|
|
} => self.globals.as_ref()?.borrow().get(idx.0 as usize)?.clone(),
|
|
NodeKind::Constant(val) => val.clone(),
|
|
_ => return None,
|
|
};
|
|
let result = match func_val {
|
|
Value::Function(f) => (f.func)(&arg_values),
|
|
_ => return None,
|
|
};
|
|
Some(self.make_constant_node(result, callee))
|
|
}
|
|
}
|