From 4f70fa2246af973961c23a68908e986adc7a2d62 Mon Sep 17 00:00:00 2001 From: Janis Date: Mon, 16 Sep 2024 16:55:04 +0200 Subject: [PATCH] comptime folding, - reduced scope of foldability to just simple expressions and declrefs to globaldecls --- src/ast2/mod.rs | 628 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 496 insertions(+), 132 deletions(-) diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index 1fda2cb..a72f756 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -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 { + 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, 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(&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::>(); - 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::>(); while let Some(node) = nodes.pop() { @@ -2738,14 +3060,14 @@ pub mod ast_gen { } } - let mut node_map = Vec::::new(); + let mut node_map = Vec::::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::>(); + 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::>(); 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(); }