//! AST 结构哈希:按语法域(statement/expression/class/...)递归计算 //! `Program` 的稳定哈希,用作编译缓存键(code cache)。 //! //! `structural_hash` 忽略绑定名(结构相等即可命中), //! `compiled_module_hash` 纳入绑定名(精确匹配避免错误复用)。 use oxide_parser::{ ArrayExpressionElement, BindingPattern, ChainElement, Class, ClassElement, Declaration, ExportDefaultDeclarationKind, Expression, ForStatementInit, ForStatementLeft, Function, ImportDeclarationSpecifier, ModuleExportName, ObjectPropertyKind, PropertyKey, SimpleAssignmentTarget, Statement, }; use std::hash::Hash; #[derive(Hash)] enum HashDomain { Statement, Expression, ClassElement, PropertyKey, ObjectPropertyKind, SimpleAssignmentTarget, } macro_rules! hash_match { ($domain:expr, $value:expr, $h:expr, { $($arms:tt)* }) => {{ $domain.hash($h); std::mem::discriminant($value).hash($h); match $value { $($arms)* } }}; } mod class; mod expression; mod property; mod statement; mod target; /// 结构哈希:忽略绑定名的 `Program` 哈希(用于粗粒度缓存命中判断)。 pub fn structural_hash(program: &oxide_parser::Program) -> u64 { hash_program(program, false) } /// 编译模块哈希:纳入绑定名的 `Program` 哈希(用于精确缓存命中判断)。 pub fn compiled_module_hash(program: &oxide_parser::Program) -> u64 { hash_program(program, true) } fn hash_program(program: &oxide_parser::Program, include_binding_names: bool) -> u64 { use std::hash::Hasher; let mut h = rustc_hash::FxHasher::default(); for stmt in &program.body { statement::hash_statement(stmt, &mut h, include_binding_names); } h.finish() } fn hash_binding_pattern(pattern: &BindingPattern, h: &mut rustc_hash::FxHasher) { if let BindingPattern::BindingIdentifier(ident) = pattern { ident.name.as_str().hash(h); } }