calculate which nodes are comptime evaluable
This commit is contained in:
parent
888517f2ea
commit
5ad0e9e8e7
303
src/ast2/mod.rs
303
src/ast2/mod.rs
|
@ -1938,6 +1938,37 @@ impl Display for Children {
|
|||
}
|
||||
|
||||
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 {
|
||||
fn get_type_of_node(
|
||||
|
@ -2241,83 +2272,185 @@ 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 is_node_comptime_evaluable(&self, cache: &mut ComptimeCache, index: Index) -> bool {
|
||||
if let Some(a) = cache.get(&index) {
|
||||
a
|
||||
} else {
|
||||
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 => todo!(),
|
||||
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!(),
|
||||
let children = self.get_node_children(index);
|
||||
|
||||
let are_children_comptime = |this: &Self, cache: &mut ComptimeCache| {
|
||||
children
|
||||
.iter()
|
||||
.all(|&i| this.is_node_comptime_evaluable(cache, i))
|
||||
};
|
||||
|
||||
let is_comptime = match tag {
|
||||
Tag::Parameter => false,
|
||||
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::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,
|
||||
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 => {
|
||||
self.is_node_comptime_evaluable(cache, data.as_index_intern().0)
|
||||
}
|
||||
Tag::ExplicitCast => {
|
||||
self.is_node_comptime_evaluable(cache, data.as_two_indices().0)
|
||||
}
|
||||
Tag::Deref | Tag::AddressOf => false,
|
||||
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::SubscriptExpr
|
||||
| Tag::Rem => are_children_comptime(self, cache),
|
||||
Tag::Assign => {
|
||||
let (left, _) = data.as_two_indices();
|
||||
cache.mark_as_dominated_by(index, left);
|
||||
are_children_comptime(self, cache)
|
||||
}
|
||||
Tag::IfExpr | Tag::IfElseExpr => are_children_comptime(self, cache),
|
||||
Tag::Root
|
||||
| Tag::File
|
||||
| Tag::FunctionProto
|
||||
| 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(
|
||||
|
@ -2464,6 +2597,7 @@ pub struct AstRenderer<'a> {
|
|||
ip: &'a InternPool,
|
||||
scopes: Vec<Index>,
|
||||
cache: TypeCache,
|
||||
comptime_cache: ComptimeCache,
|
||||
}
|
||||
|
||||
impl<'a> AstRenderer<'a> {
|
||||
|
@ -2478,6 +2612,7 @@ impl<'a> AstRenderer<'a> {
|
|||
ip,
|
||||
scopes: Vec::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 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 {
|
||||
self.render_node(w, indent + 1, child)?;
|
||||
|
@ -2577,7 +2720,14 @@ pub mod ast_gen {
|
|||
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) {
|
||||
let mut nodes = self
|
||||
|
@ -2611,6 +2761,7 @@ pub mod ast_gen {
|
|||
let pointee = self.ast.datas[pointee.index()].as_intern();
|
||||
variant!( self.intern.get_key(pointee) => intern::Key::PointerType { pointee, flags });
|
||||
|
||||
// get interened value from constant node
|
||||
let length = {
|
||||
let value = self.ast.datas[length.index()].as_index_intern().1;
|
||||
|
||||
|
|
Loading…
Reference in a new issue