comptime folding,
- reduced scope of foldability to just simple expressions and declrefs to globaldecls
This commit is contained in:
parent
3d014ad985
commit
4f70fa2246
628
src/ast2/mod.rs
628
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<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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue