calculate which nodes are comptime evaluable

This commit is contained in:
Janis 2024-09-16 00:15:39 +02:00
parent 888517f2ea
commit 5ad0e9e8e7

View file

@ -1938,6 +1938,37 @@ impl Display for Children {
} }
type TypeCache = BTreeMap<Index, intern::Index>; type TypeCache = BTreeMap<Index, intern::Index>;
// type ComptimeCache = BTreeMap<Index, bool>;
#[derive(Debug, Default)]
struct ComptimeCache {
inner: BTreeMap<Index, bool>,
// this is (a,b) where b dominates a
// meaning:
// when a is marked as runtime, b can be updated to be runtime as well.
dependencies: BTreeMap<Index, Index>,
}
impl ComptimeCache {
fn get(&self, key: &Index) -> Option<bool> {
self.inner.get(key).cloned()
}
fn insert(&mut self, key: Index, value: bool) {
self.inner.insert(key, value);
if !value {
self.set_runtime(key);
}
}
fn mark_as_dominated_by(&mut self, a: Index, b: Index) {
self.dependencies.insert(a, b);
}
fn set_runtime(&mut self, key: Index) {
self.inner.insert(key, false);
if let Some(&dom) = self.dependencies.get(&key) {
self.set_runtime(dom);
}
}
}
impl Ast { impl Ast {
fn get_type_of_node( fn get_type_of_node(
@ -2241,83 +2272,185 @@ impl Ast {
} }
} }
fn comptime_value_of_node( fn is_node_comptime_evaluable(&self, cache: &mut ComptimeCache, index: Index) -> bool {
&self, if let Some(a) = cache.get(&index) {
ip: &InternPool, a
pointer_bits: u16, } else {
cache: &mut TypeCache,
index: Index,
) -> crate::comptime::ComptimeNumber {
let tag = self.tags[index.index()]; let tag = self.tags[index.index()];
let data = self.datas[index.index()]; let data = self.datas[index.index()];
match tag { let children = self.get_node_children(index);
Tag::Root => todo!(),
Tag::File => todo!(), let are_children_comptime = |this: &Self, cache: &mut ComptimeCache| {
Tag::FunctionProto => todo!(), children
Tag::FunctionDecl => todo!(), .iter()
Tag::ParameterList => todo!(), .all(|&i| this.is_node_comptime_evaluable(cache, i))
Tag::Parameter => todo!(), };
Tag::Block => todo!(),
Tag::BlockTrailingExpr => todo!(), let is_comptime = match tag {
Tag::Constant => { Tag::Parameter => false,
let (ty, value) = data.as_index_intern(); Tag::Block | Tag::BlockTrailingExpr => are_children_comptime(self, cache),
let ty = self.get_type_of_node(ip, cache, ty); Tag::Constant => true,
interned_type_and_value_to_comptime_number(ip, pointer_bits, ty, value) 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::ExprStmt => todo!(), Tag::GlobalDecl => true,
Tag::ReturnStmt => todo!(), Tag::StructDecl => true,
Tag::ReturnExprStmt => todo!(), Tag::FieldDecl => true,
Tag::VarDecl => todo!(), Tag::DeclRef => self.tags[data.as_index().index()] == Tag::GlobalDecl,
Tag::MutVarDecl => todo!(), Tag::InternedType | Tag::PointerType | Tag::ArrayType | Tag::TypeDeclRef => true,
Tag::VarDeclAssignment => todo!(), Tag::CallExpr => false,
Tag::MutVarDeclAssignment => todo!(), Tag::FieldAccess => {
Tag::GlobalDecl => todo!(), let parent = data.as_index_intern().0;
Tag::StructDecl => todo!(), cache.mark_as_dominated_by(index, parent);
Tag::FieldDecl => todo!(), self.is_node_comptime_evaluable(cache, parent)
Tag::DeclRef => todo!(), }
Tag::DeclRefUnresolved => todo!(), Tag::ArgumentList => are_children_comptime(self, cache),
Tag::InternedType => todo!(), Tag::Argument => self.is_node_comptime_evaluable(cache, data.as_index()),
Tag::TypeDeclRef => todo!(), Tag::NamedArgument => {
Tag::TypeDeclRefUnresolved => todo!(), self.is_node_comptime_evaluable(cache, data.as_index_intern().0)
Tag::PointerType => todo!(), }
Tag::ArrayType => todo!(), Tag::ExplicitCast => {
Tag::CallExpr => todo!(), self.is_node_comptime_evaluable(cache, data.as_two_indices().0)
Tag::FieldAccess => todo!(), }
Tag::ArgumentList => todo!(), Tag::Deref | Tag::AddressOf => false,
Tag::Argument => todo!(), Tag::Not
Tag::NamedArgument => todo!(), | Tag::Negate
Tag::ExplicitCast => todo!(), | Tag::Or
Tag::Deref => todo!(), | Tag::And
Tag::AddressOf => todo!(), | Tag::BitOr
Tag::Not => todo!(), | Tag::BitXOr
Tag::Negate => todo!(), | Tag::BitAnd
Tag::Or => todo!(), | Tag::Eq
Tag::And => todo!(), | Tag::NEq
Tag::BitOr => todo!(), | Tag::Lt
Tag::BitXOr => todo!(), | Tag::Gt
Tag::BitAnd => todo!(), | Tag::Le
Tag::Eq => todo!(), | Tag::Ge
Tag::NEq => todo!(), | Tag::Shl
Tag::Lt => todo!(), | Tag::Shr
Tag::Gt => todo!(), | Tag::Add
Tag::Le => todo!(), | Tag::Sub
Tag::Ge => todo!(), | Tag::Mul
Tag::Shl => todo!(), | Tag::Div
Tag::Shr => todo!(), | Tag::SubscriptExpr
Tag::Add => todo!(), | Tag::Rem => are_children_comptime(self, cache),
Tag::Sub => todo!(), Tag::Assign => {
Tag::Mul => todo!(), let (left, _) = data.as_two_indices();
Tag::Div => todo!(), cache.mark_as_dominated_by(index, left);
Tag::Rem => todo!(), are_children_comptime(self, cache)
Tag::Assign => todo!(), }
Tag::SubscriptExpr => todo!(), Tag::IfExpr | Tag::IfElseExpr => are_children_comptime(self, cache),
Tag::IfExpr => todo!(), Tag::Root
Tag::IfElseExpr => todo!(), | Tag::File
Tag::Error => todo!(), | Tag::FunctionProto
Tag::Undefined => todo!(), | Tag::FunctionDecl
| Tag::ParameterList
| Tag::ExprStmt
| Tag::DeclRefUnresolved
| Tag::TypeDeclRefUnresolved
| Tag::Error
| Tag::Undefined => false,
};
cache.insert(index, is_comptime);
is_comptime
} }
} }
// 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()];
// 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!(),
// }
// }
} }
fn interned_type_and_value_to_comptime_number( fn interned_type_and_value_to_comptime_number(
@ -2464,6 +2597,7 @@ pub struct AstRenderer<'a> {
ip: &'a InternPool, ip: &'a InternPool,
scopes: Vec<Index>, scopes: Vec<Index>,
cache: TypeCache, cache: TypeCache,
comptime_cache: ComptimeCache,
} }
impl<'a> AstRenderer<'a> { impl<'a> AstRenderer<'a> {
@ -2478,6 +2612,7 @@ impl<'a> AstRenderer<'a> {
ip, ip,
scopes: Vec::new(), scopes: Vec::new(),
cache: TypeCache::new(), cache: TypeCache::new(),
comptime_cache: ComptimeCache::default(),
} }
} }
@ -2498,7 +2633,15 @@ impl<'a> AstRenderer<'a> {
let children = Children(self.ast.get_node_children(node)); let children = Children(self.ast.get_node_children(node));
let ty = self.ast.get_type_of_node(self.ip, &mut self.cache, node); let ty = self.ast.get_type_of_node(self.ip, &mut self.cache, node);
writeln_indented!(indent, w, "{node} ({ty}) = ({loc}) {tag:?} {}", children)?; let is_comptime = self
.ast
.is_node_comptime_evaluable(&mut self.comptime_cache, node);
writeln_indented!(
indent * 2,
w,
"{node} {}({ty}) = ({loc}) {tag:?} {children}",
if is_comptime { "CONST " } else { "" }
)?;
for child in children.0 { for child in children.0 {
self.render_node(w, indent + 1, child)?; self.render_node(w, indent + 1, child)?;
@ -2577,7 +2720,14 @@ pub mod ast_gen {
AstRenderer::new(&self.ast, &self.intern, &self.syms) AstRenderer::new(&self.ast, &self.intern, &self.syms)
} }
pub fn fold_and_typecheck(&mut self) {} pub fn fold_and_typecheck(&mut self) {
enum Asdf {
Pre(Index),
Post(Index),
}
let mut nodes = self.ast.get_root_file_indices().collect::<Vec<_>>();
let mut cache = TypeCache::new();
}
pub fn intern_types(&mut self) { pub fn intern_types(&mut self) {
let mut nodes = self let mut nodes = self
@ -2611,6 +2761,7 @@ pub mod ast_gen {
let pointee = self.ast.datas[pointee.index()].as_intern(); let pointee = self.ast.datas[pointee.index()].as_intern();
variant!( self.intern.get_key(pointee) => intern::Key::PointerType { pointee, flags }); variant!( self.intern.get_key(pointee) => intern::Key::PointerType { pointee, flags });
// get interened value from constant node
let length = { let length = {
let value = self.ast.datas[length.index()].as_index_intern().1; let value = self.ast.datas[length.index()].as_index_intern().1;