feat: Implement efficient node lookup table using node indices (#463)

Major Changes:
- Add generic Lookup<T> structure for efficient O(1) module-level data access
- Combine separate scope and order lookups into unified QuerySchedule structure
- Add query_schedule field to Interpreter for dedicated user query scheduling
- Refactor loop hoising to separate module
- Use efficient lookup for loop vars
- Also added more tests for loops

Key Concept:
- Ensure module context and indexing stay synchronized during function calls

Testing:
- All scheduler and interpreter tests passing

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2025-08-26 15:01:45 -05:00
committed by GitHub
parent c43c94559a
commit 85753aaf37
8 changed files with 599 additions and 322 deletions
+21 -5
View File
@@ -52,11 +52,27 @@ fn analyze_file(regos: &[String], expected_scopes: &[Scope]) -> Result<()> {
let analyzer = Analyzer::new();
let schedule = analyzer.analyze(&modules)?;
let mut scopes: Vec<(Ref<Query>, &crate::scheduler::Scope)> = schedule
.scopes
.iter()
.map(|(r, s)| (r.clone(), s))
.collect();
// Collect all queries from modules to create the mapping
let mut all_queries = Vec::new();
for (module_idx, module) in modules.iter().enumerate() {
for rule in &module.policy {
if let Rule::Spec { bodies, .. } = rule.as_ref() {
for body in bodies {
all_queries.push((module_idx as u32, body.query.qidx, body.query.clone()));
}
}
}
}
let mut scopes = Vec::new();
for (module_idx, qidx, query) in all_queries.iter() {
// Find the corresponding query schedule
if let Some(query_schedule) = schedule.queries.get(*module_idx, *qidx) {
scopes.push((query.clone(), &query_schedule.scope));
}
}
scopes.sort_by(|a, b| a.0.span.line.cmp(&b.0.span.line));
for (idx, (_, scope)) in scopes.iter().enumerate() {
if idx > expected_scopes.len() {