diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index 7f4533b..f63d17d 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -1938,6 +1938,37 @@ impl Display for Children { } type TypeCache = BTreeMap; +// type ComptimeCache = BTreeMap; + +#[derive(Debug, Default)] +struct ComptimeCache { + inner: BTreeMap, + // 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, +} + +impl ComptimeCache { + fn get(&self, key: &Index) -> Option { + 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, 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::>(); + 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;