comptime folding,

- reduced scope of foldability to just simple expressions and declrefs to globaldecls
This commit is contained in:
Janis 2024-09-16 16:55:04 +02:00
parent 3d014ad985
commit 4f70fa2246

View file

@ -9,7 +9,10 @@ use std::{
use intern::{InternPool, PointerFlags, StructFlags};
use num_bigint::BigInt;
use crate::{lexer::SourceLocation, tokens::Token, writeln_indented};
use crate::{
ast::FloatingType, comptime::ComptimeNumber, lexer::SourceLocation, tokens::Token,
writeln_indented,
};
pub mod intern {
use std::{
@ -21,6 +24,7 @@ pub mod intern {
use num_bigint::{BigInt, BigUint, Sign};
use crate::{
ast::IntegralType,
common::{from_lo_hi_dwords, into_lo_hi_dwords},
variant,
};
@ -533,8 +537,74 @@ pub mod intern {
}
}
}
pub fn from_ast1_type(&self, pointer_bits: u16, ty: &crate::ast::Type) -> Index {
match ty {
crate::ast::Type::Bool => self.get_bool_type(),
crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(),
crate::ast::Type::Integer(i) => self.get_assume_present(&{
if i.signed {
Key::SIntType { bits: i.bits }
} else {
Key::UIntType { bits: i.bits }
}
}),
crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => {
self.get_f32_type()
}
crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => {
self.get_f64_type()
}
crate::ast::Type::Pointer { constness, pointee } => {
self.get_assume_present(&Key::PointerType {
pointee: self.from_ast1_type(pointer_bits, &pointee),
flags: PointerFlags::new(*constness, false, false),
})
}
crate::ast::Type::Fn { .. } => {
unimplemented!()
}
_ => {
todo!()
}
}
}
pub fn as_ast1_type(&self, pointer_bits: u16, index: Index) -> crate::ast::Type {
use crate::ast::Type;
match self.get_key(index) {
Key::UIntType { bits } => Type::Integer(IntegralType::new(false, bits)),
Key::SIntType { bits } => Type::Integer(IntegralType::new(true, bits)),
Key::SimpleType { ty } => match ty {
SimpleType::F32 => Type::Floating(crate::ast::FloatingType::Binary32),
SimpleType::F64 => Type::Floating(crate::ast::FloatingType::Binary64),
SimpleType::Bool => Type::Bool,
SimpleType::Void => Type::Void,
SimpleType::USize => Type::Integer(IntegralType::new(false, pointer_bits)),
SimpleType::ISize => Type::Integer(IntegralType::new(true, pointer_bits)),
SimpleType::ComptimeInt => Type::comptime_number(),
},
Key::PointerType { pointee, flags } => Type::Pointer {
constness: flags.is_const,
pointee: Box::new(self.as_ast1_type(pointer_bits, pointee)),
},
Key::FunctionType {
return_type,
parameters,
} => Type::Fn {
parameter_types: parameters
.into_iter()
.map(|i| self.as_ast1_type(pointer_bits, i))
.collect(),
return_type: Box::new(self.as_ast1_type(pointer_bits, return_type)),
},
_ => unimplemented!(),
}
}
}
pub const AMD64_POINTER_BITS: u16 = 64;
impl InternPool {
pub fn create() -> Self {
let mut this = Self {
@ -617,6 +687,7 @@ pub mod intern {
_ = self.extend_words(words);
self.create_item(Tag::NegativeInt, i)
}
Key::UIntType { bits } => self.create_item(Tag::UIntType, bits as u32),
Key::SIntType { bits } => self.create_item(Tag::SIntType, bits as u32),
Key::SimpleType { ty } => self.create_item(Tag::SimpleType, ty as u8 as u32),
@ -1122,6 +1193,55 @@ enum Tag {
Undefined,
}
impl Tag {
fn is_type(&self) -> bool {
match self {
Tag::TypeDeclRef
| Tag::TypeDeclRefUnresolved
| Tag::PointerType
| Tag::InternedType
| Tag::ArrayType
| Tag::StructDecl => true,
_ => false,
}
}
fn is_expr(&self) -> bool {
match self {
Tag::Constant
| Tag::DeclRef
| Tag::Deref
| Tag::CallExpr
| Tag::AddressOf
| Tag::Not
| Tag::Negate
| Tag::Or
| Tag::And
| Tag::BitOr
| Tag::BitXOr
| Tag::BitAnd
| Tag::Eq
| Tag::NEq
| Tag::Lt
| Tag::Gt
| Tag::Le
| Tag::Ge
| Tag::Shl
| Tag::Shr
| Tag::Add
| Tag::Sub
| Tag::Mul
| Tag::Div
| Tag::Rem
| Tag::SubscriptExpr
| Tag::IfExpr
| Tag::IfElseExpr
| Tag::Block
| &Tag::BlockTrailingExpr => true,
_ => false,
}
}
}
#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
enum ParseError {
#[error("Unexpected end of token iter.")]
@ -2134,7 +2254,7 @@ impl Ast {
Tag::FieldDecl => self.get_type_of_node(ip, cache, data.as_index_intern().0),
Tag::InternedType => data.as_intern(),
Tag::TypeDeclRef | Tag::TypeDeclRefUnresolved | Tag::PointerType | Tag::ArrayType => {
unreachable!()
ip.get_void_type()
}
};
@ -2289,25 +2409,24 @@ impl Ast {
let is_comptime = match tag {
Tag::Parameter => false,
Tag::Block | Tag::BlockTrailingExpr => are_children_comptime(self, cache),
// Tag::Block | Tag::BlockTrailingExpr => are_children_comptime(self, cache),
Tag::Constant => true,
Tag::ReturnStmt => true,
Tag::ReturnExprStmt => are_children_comptime(self, cache),
Tag::VarDecl | Tag::MutVarDecl => true,
Tag::VarDeclAssignment | Tag::MutVarDeclAssignment => {
are_children_comptime(self, cache)
}
Tag::MutVarDecl | Tag::MutVarDeclAssignment => false,
// Tag::VarDecl => true,
Tag::VarDeclAssignment => are_children_comptime(self, cache),
Tag::GlobalDecl => true,
Tag::StructDecl => true,
Tag::FieldDecl => true,
Tag::DeclRef => self.tags[data.as_index().index()] == Tag::GlobalDecl,
Tag::InternedType | Tag::PointerType | Tag::ArrayType | Tag::TypeDeclRef => true,
Tag::CallExpr => false, // are_children_comptime(self, cache),
Tag::FieldAccess => {
let parent = data.as_index_intern().0;
cache.mark_as_dominated_by(index, parent);
self.is_node_comptime_evaluable(cache, parent)
}
// Tag::CallExpr => are_children_comptime(self, cache),
// Tag::FieldAccess => {
// let parent = data.as_index_intern().0;
// cache.mark_as_dominated_by(index, parent);
// self.is_node_comptime_evaluable(cache, parent)
// }
Tag::ArgumentList => are_children_comptime(self, cache),
Tag::Argument => self.is_node_comptime_evaluable(cache, data.as_index()),
Tag::NamedArgument => {
@ -2343,7 +2462,7 @@ impl Ast {
cache.mark_as_dominated_by(index, left);
are_children_comptime(self, cache)
}
Tag::IfExpr | Tag::IfElseExpr => are_children_comptime(self, cache),
// Tag::IfExpr | Tag::IfElseExpr => are_children_comptime(self, cache),
Tag::Root
| Tag::File
| Tag::FunctionProto
@ -2354,6 +2473,7 @@ impl Ast {
| Tag::TypeDeclRefUnresolved
| Tag::Error
| Tag::Undefined => false,
_ => false,
};
cache.insert(index, is_comptime);
@ -2362,95 +2482,283 @@ impl Ast {
}
}
// fn comptime_value_of_node(
// &self,
// ip: &InternPool,
// pointer_bits: u16,
// cache: &mut TypeCache,
// index: Index,
// ) -> crate::comptime::ComptimeNumber {
// let tag = self.tags[index.index()];
// let data = self.datas[index.index()];
fn comptime_value_of_node(
&self,
ip: &InternPool,
pointer_bits: u16,
cache: &mut TypeCache,
index: Index,
) -> Option<crate::comptime::ComptimeNumber> {
let tag = self.tags[index.index()];
let data = self.datas[index.index()];
// match tag {
// Tag::Root => todo!(),
// Tag::File => todo!(),
// Tag::FunctionProto => todo!(),
// Tag::FunctionDecl => todo!(),
// Tag::ParameterList => todo!(),
// Tag::Parameter => todo!(),
// Tag::Block => todo!(),
// Tag::BlockTrailingExpr => {
// let (a, b) = data.as_extra_range();
// if a != b {
// self.comptime_value_of_node(
// ip,
// pointer_bits,
// cache,
// Index::new(self.extra[b - 1]),
// )
// } else {
// None
// }
// }
// Tag::Constant => {
// let (ty, value) = data.as_index_intern();
// let ty = self.get_type_of_node(ip, cache, ty);
// interned_type_and_value_to_comptime_number(ip, pointer_bits, ty, value)
// }
// Tag::ExprStmt => todo!(),
// Tag::ReturnStmt => todo!(),
// Tag::ReturnExprStmt => todo!(),
// Tag::VarDecl => todo!(),
// Tag::MutVarDecl => todo!(),
// Tag::VarDeclAssignment => todo!(),
// Tag::MutVarDeclAssignment => todo!(),
// Tag::GlobalDecl => todo!(),
// Tag::StructDecl => todo!(),
// Tag::FieldDecl => todo!(),
// Tag::DeclRef => todo!(),
// Tag::DeclRefUnresolved => todo!(),
// Tag::InternedType => todo!(),
// Tag::TypeDeclRef => todo!(),
// Tag::TypeDeclRefUnresolved => todo!(),
// Tag::PointerType => todo!(),
// Tag::ArrayType => todo!(),
// Tag::CallExpr => todo!(),
// Tag::FieldAccess => todo!(),
// Tag::ArgumentList => todo!(),
// Tag::Argument => todo!(),
// Tag::NamedArgument => todo!(),
// Tag::ExplicitCast => todo!(),
// Tag::Deref => todo!(),
// Tag::AddressOf => todo!(),
// Tag::Not => todo!(),
// Tag::Negate => todo!(),
// Tag::Or => todo!(),
// Tag::And => todo!(),
// Tag::BitOr => todo!(),
// Tag::BitXOr => todo!(),
// Tag::BitAnd => todo!(),
// Tag::Eq => todo!(),
// Tag::NEq => todo!(),
// Tag::Lt => todo!(),
// Tag::Gt => todo!(),
// Tag::Le => todo!(),
// Tag::Ge => todo!(),
// Tag::Shl => todo!(),
// Tag::Shr => todo!(),
// Tag::Add => todo!(),
// Tag::Sub => todo!(),
// Tag::Mul => todo!(),
// Tag::Div => todo!(),
// Tag::Rem => todo!(),
// Tag::Assign => todo!(),
// Tag::SubscriptExpr => todo!(),
// Tag::IfExpr => todo!(),
// Tag::IfElseExpr => todo!(),
// Tag::Error => todo!(),
// Tag::Undefined => todo!(),
// }
// }
match tag {
Tag::Constant => {
let (ty, value) = data.as_index_intern();
let ty = self.get_type_of_node(ip, cache, ty);
Some(interned_type_and_value_to_comptime_number(
ip,
pointer_bits,
ty,
value,
))
}
Tag::GlobalDecl => {
let (_, offset) = data.as_intern_and_extra_offset();
self.comptime_value_of_node(
ip,
pointer_bits,
cache,
Index::new(self.extra[offset + 1]),
)
}
Tag::VarDeclAssignment => {
let (a, _) = data.as_extra_range();
self.comptime_value_of_node(ip, pointer_bits, cache, Index::new(self.extra[a + 1]))
}
Tag::DeclRef => self.comptime_value_of_node(ip, pointer_bits, cache, data.as_index()),
Tag::ExplicitCast => {
let (expr, ty) = data.as_two_indices();
let ty = ip.as_ast1_type(
intern::AMD64_POINTER_BITS,
self.datas[ty.index()].as_intern(),
);
let val = self.comptime_value_of_node(ip, pointer_bits, cache, expr);
val.and_then(|i| i.explicit_cast(ty).ok())
}
Tag::Add => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.add(b).ok())
})
}
Tag::Sub => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.sub(b).ok())
})
}
Tag::Mul => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.mul(b).ok())
})
}
Tag::Div => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.div(b).ok())
})
}
Tag::Rem => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.rem(b).ok())
})
}
Tag::Shl => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.shl(b).ok())
})
}
Tag::Shr => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.shr(b).ok())
})
}
Tag::BitAnd => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.bitand(b).ok())
})
}
Tag::BitOr => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.bitor(b).ok())
})
}
Tag::BitXOr => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.bitxor(b).ok())
})
}
Tag::And => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.and(b).ok())
})
}
Tag::Or => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.or(b).ok())
})
}
Tag::Eq => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.eq(b).ok())
})
}
Tag::NEq => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.eq(b).and_then(|i| i.not()).ok())
})
}
Tag::Gt => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.gt(b).ok())
})
}
Tag::Lt => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.lt(b).ok())
})
}
Tag::Le => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.le(b).ok())
})
}
Tag::Ge => {
let (a, b) = data.as_two_indices();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| {
self.comptime_value_of_node(ip, pointer_bits, cache, b)
.and_then(|b| a.ge(b).ok())
})
}
Tag::Not => {
let a = data.as_index();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| a.not().ok())
}
Tag::Negate => {
let a = data.as_index();
self.comptime_value_of_node(ip, pointer_bits, cache, a)
.and_then(|a| a.neg().ok())
}
_ => None,
}
}
}
fn comptime_number_to_interned_type_and_value(
ip: &mut InternPool,
pointer_bits: u16,
comptime: ComptimeNumber,
) -> (intern::Index, intern::Index) {
use crate::ast::IntegralType;
let (value, ty) = comptime.into_bytes_and_type();
let value = match ty {
crate::ast::Type::Bool => {
if value.get(0) != Some(&1) {
ip.get_false_value()
} else {
ip.get_true_value()
}
}
crate::ast::Type::Integer(IntegralType { bits: 65.., .. })
| crate::ast::Type::ComptimeNumber => {
let bigint = BigInt::from_signed_bytes_le(&value);
if bigint.sign() == num_bigint::Sign::Minus {
ip.get_or_insert(intern::Key::NegativeInt { bigint })
} else {
ip.get_or_insert(intern::Key::PositiveInt { bigint })
}
}
crate::ast::Type::Integer(i) => match i.bits {
..=32 => {
let mut buf = [0u8; 4];
buf[..value.len()].copy_from_slice(&value[..]);
if i.signed {
ip.get_or_insert(intern::Key::SIntSmall {
bits: i32::from_le_bytes(buf),
})
} else {
ip.get_or_insert(intern::Key::UIntSmall {
bits: u32::from_le_bytes(buf),
})
}
}
..=64 => {
let mut buf = [0u8; 8];
buf[..value.len()].copy_from_slice(&value[..]);
if i.signed {
ip.get_or_insert(intern::Key::SInt64 {
bits: i64::from_le_bytes(buf),
})
} else {
ip.get_or_insert(intern::Key::UInt64 {
bits: u64::from_le_bytes(buf),
})
}
}
_ => unreachable!(),
},
crate::ast::Type::Floating(FloatingType::Binary32) => {
let mut buf = [0u8; 4];
buf[..value.len()].copy_from_slice(&value[..]);
ip.get_or_insert(intern::Key::F32 {
bits: f32::from_le_bytes(buf),
})
}
crate::ast::Type::Floating(FloatingType::Binary64) => {
let mut buf = [0u8; 8];
buf[..value.len()].copy_from_slice(&value[..]);
ip.get_or_insert(intern::Key::F64 {
bits: f64::from_le_bytes(buf),
})
}
_ => unimplemented!(),
};
let ty = ip.from_ast1_type(pointer_bits, &ty);
(value, ty)
}
fn interned_type_and_value_to_comptime_number(
@ -2595,11 +2903,39 @@ pub struct AstRenderer<'a> {
#[allow(dead_code)]
syms: &'a crate::symbol_table::syms2::Symbols,
ip: &'a InternPool,
scopes: Vec<Index>,
cache: TypeCache,
comptime_cache: ComptimeCache,
}
pub struct NodeDisplay<'a> {
node: Index,
ast: &'a Ast,
ip: &'a InternPool,
}
impl<'a> Display for NodeDisplay<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let node = self.node;
let tag = self.ast.tags[node.index()];
let loc = self.ast.source_locs[node.index()];
let children = Children(self.ast.get_node_children(node));
let ty = self
.ast
.get_type_of_node(self.ip, &mut TypeCache::new(), node);
let is_comptime = self
.ast
.is_node_comptime_evaluable(&mut ComptimeCache::default(), node);
writeln!(
f,
"{node} {}({ty}) = ({loc}) {tag:?} {children}",
if is_comptime { "CONST " } else { "" }
)?;
Ok(())
}
}
impl<'a> AstRenderer<'a> {
pub fn new(
ast: &'a Ast,
@ -2610,7 +2946,6 @@ impl<'a> AstRenderer<'a> {
ast,
syms,
ip,
scopes: Vec::new(),
cache: TypeCache::new(),
comptime_cache: ComptimeCache::default(),
}
@ -2624,12 +2959,6 @@ impl<'a> AstRenderer<'a> {
) -> core::fmt::Result {
let tag = self.ast.tags[node.index()];
let loc = self.ast.source_locs[node.index()];
match tag {
Tag::File | Tag::FunctionDecl | Tag::Block | Tag::BlockTrailingExpr => {
self.scopes.push(node);
}
_ => {}
}
let children = Children(self.ast.get_node_children(node));
let ty = self.ast.get_type_of_node(self.ip, &mut self.cache, node);
@ -2647,13 +2976,6 @@ impl<'a> AstRenderer<'a> {
self.render_node(w, indent + 1, child)?;
}
match tag {
Tag::File | Tag::FunctionDecl | Tag::Block | Tag::BlockTrailingExpr => {
self.scopes.pop();
}
_ => {}
}
Ok(())
}
fn render<W: core::fmt::Write>(&mut self, w: &mut W) -> core::fmt::Result {
@ -2720,16 +3042,16 @@ pub mod ast_gen {
AstRenderer::new(&self.ast, &self.intern, &self.syms)
}
pub fn fold_and_typecheck(&mut self) {
enum Asdf {
Pre(Index),
Post(Index),
pub fn node_display(&self, node: Index) -> NodeDisplay<'_> {
NodeDisplay {
node,
ast: &self.ast,
ip: &self.intern,
}
let mut nodes = self.ast.get_root_file_indices().collect::<Vec<_>>();
let mut cache = TypeCache::new();
}
pub fn create_comptime_folding_graph(&mut self) {
pub fn create_comptime_folding_graph(&mut self, pointer_bits: u16) {
let mut type_cache = TypeCache::new();
let mut cache = ComptimeCache::default();
let mut nodes = self.ast.get_root_file_indices().collect::<Vec<_>>();
while let Some(node) = nodes.pop() {
@ -2738,14 +3060,14 @@ pub mod ast_gen {
}
}
let mut node_map = Vec::<u32>::new();
let mut node_map = Vec::<Index>::new();
let edges = cache
.inner
.iter()
.filter(|(_, b)| **b)
.map(|(e, _)| self.ast.get_node_children(*e).into_iter().map(|d| (*e, d)))
.flatten()
.map(|(a, b)| (a.into_u32(), b.into_u32()))
// .map(|(a, b)| (a.into_u32(), b.into_u32()))
.map(|(a, b)| {
(
node_map.iter().position(|&i| i == a).unwrap_or_else(|| {
@ -2760,21 +3082,63 @@ pub mod ast_gen {
})
.collect::<Vec<_>>();
let extra_nodes = cache
.inner
.iter()
.filter(|(i, b)| **b)
.filter_map(|(i, _)| (!node_map.contains(i)).then(|| node_map.push(*i)))
.count();
eprintln!("cache: {cache:?}");
eprintln!("node_map: {node_map:?}");
eprintln!("edges: {edges:?}");
let mut graph = petgraph::stable_graph::StableDiGraph::<(), ()>::from_edges(edges);
for _ in 0..extra_nodes {
graph.add_node(());
}
std::fs::write(
"comptime_graph.dot",
&format!("{:?}", petgraph::dot::Dot::new(&graph)),
&format!(
"{:?}",
petgraph::dot::Dot::with_attr_getters(
&graph,
&[],
&|graph, edgeref| { "".to_string() },
&|graph, noderef| {
format!("label = \"{}\"", node_map[noderef.0.index()])
}
)
),
)
.expect("writing comptime graph repr");
let a = graph
.externals(petgraph::Direction::Outgoing)
.collect::<Vec<_>>();
while let Some(external) = graph.externals(petgraph::Direction::Outgoing).next() {
_ = node_map[external.index()];
let node = node_map[external.index()];
if !(self.ast.tags[node.index()] == Tag::Constant
|| self.ast.tags[node.index()].is_type())
&& self.ast.tags[node.index()].is_expr()
{
eprintln!("folding {node}:\n{}", self.node_display(node));
let value = self
.ast
.comptime_value_of_node(&self.intern, pointer_bits, &mut type_cache, node)
.expect(&format!("{node} has value of None?"));
let (value, ty) = comptime_number_to_interned_type_and_value(
&mut self.intern,
pointer_bits,
value,
);
let ty = self.ast.push_interend_type(ty, self.ast.get_loc(node));
self.ast.set_tag_data_source_loc(
node,
Tag::Constant,
Data::index_and_intern(ty, value),
self.ast.get_loc(node),
);
} else {
eprintln!("rejecting {node}:\n{}", self.node_display(node));
}
// comptime fold node
graph.remove_node(external);
}
@ -4345,7 +4709,7 @@ pub mod ast_gen {
self.ast.set_root([file]);
eprintln!("resolving decls:");
self.resolve_decl_refs();
self.create_comptime_folding_graph();
self.create_comptime_folding_graph(intern::AMD64_POINTER_BITS);
eprintln!("interning types:");
self.intern_types();
}