@@ -13,6 +13,7 @@ use super::destructuring_planner::{
1313use crate :: ast:: { Expr , ExprRef , Literal , LiteralStmt , Module , Query , Ref , Rule , RuleHead } ;
1414use crate :: compiler:: context:: { ContextType , ScopeContext } ;
1515use crate :: lookup:: Lookup ;
16+ use crate :: lookup:: LookupResult ;
1617use crate :: scheduler:: compute_module_globals;
1718use crate :: * ;
1819use anyhow:: { anyhow, Result } ;
@@ -147,43 +148,87 @@ impl HoistedLoopsLookup {
147148 }
148149
149150 /// Store hoisted loops for a statement
150- pub fn set_statement_loops ( & mut self , module_idx : u32 , stmt_idx : u32 , loops : Vec < HoistedLoop > ) {
151- self . statement_loops . set ( module_idx, stmt_idx, loops) ;
151+ pub fn set_statement_loops (
152+ & mut self ,
153+ module_idx : u32 ,
154+ stmt_idx : u32 ,
155+ loops : Vec < HoistedLoop > ,
156+ ) -> Result < ( ) > {
157+ self . statement_loops
158+ . set_checked ( module_idx, stmt_idx, loops)
159+ . map_err ( |err| anyhow ! ( "statement_loops out of bounds: {err}" ) )
152160 }
153161
154162 /// Get hoisted loops for a statement
155- pub fn get_statement_loops ( & self , module_idx : u32 , stmt_idx : u32 ) -> Option < & Vec < HoistedLoop > > {
163+ pub fn get_statement_loops (
164+ & self ,
165+ module_idx : u32 ,
166+ stmt_idx : u32 ,
167+ ) -> LookupResult < Option < & Vec < HoistedLoop > > > {
156168 self . statement_loops . get_checked ( module_idx, stmt_idx)
157169 }
158170
159171 /// Store hoisted loops for an expression (output expressions)
160- pub fn set_expr_loops ( & mut self , module_idx : u32 , expr_idx : u32 , loops : Vec < HoistedLoop > ) {
161- self . expr_loops . set ( module_idx, expr_idx, loops) ;
172+ pub fn set_expr_loops (
173+ & mut self ,
174+ module_idx : u32 ,
175+ expr_idx : u32 ,
176+ loops : Vec < HoistedLoop > ,
177+ ) -> Result < ( ) > {
178+ self . expr_loops
179+ . set_checked ( module_idx, expr_idx, loops)
180+ . map_err ( |err| anyhow ! ( "expr_loops out of bounds: {err}" ) )
162181 }
163182
164183 /// Get hoisted loops for an expression
165- pub fn get_expr_loops ( & self , module_idx : u32 , expr_idx : u32 ) -> Option < & Vec < HoistedLoop > > {
184+ pub fn get_expr_loops (
185+ & self ,
186+ module_idx : u32 ,
187+ expr_idx : u32 ,
188+ ) -> LookupResult < Option < & Vec < HoistedLoop > > > {
166189 self . expr_loops . get_checked ( module_idx, expr_idx)
167190 }
168191
169192 /// Store the compilation context for a query
170- pub fn set_query_context ( & mut self , module_idx : u32 , query_idx : u32 , context : ScopeContext ) {
171- self . query_contexts . set ( module_idx, query_idx, context) ;
193+ pub fn set_query_context (
194+ & mut self ,
195+ module_idx : u32 ,
196+ query_idx : u32 ,
197+ context : ScopeContext ,
198+ ) -> Result < ( ) > {
199+ self . query_contexts
200+ . set_checked ( module_idx, query_idx, context)
201+ . map_err ( |err| anyhow ! ( "query_contexts out of bounds: {err}" ) )
172202 }
173203
174204 /// Store a binding plan for an expression
175- pub fn set_expr_binding_plan ( & mut self , module_idx : u32 , expr_idx : u32 , plan : BindingPlan ) {
176- self . expr_binding_plans . set ( module_idx, expr_idx, plan) ;
205+ pub fn set_expr_binding_plan (
206+ & mut self ,
207+ module_idx : u32 ,
208+ expr_idx : u32 ,
209+ plan : BindingPlan ,
210+ ) -> Result < ( ) > {
211+ self . expr_binding_plans
212+ . set_checked ( module_idx, expr_idx, plan)
213+ . map_err ( |err| anyhow ! ( "expr_binding_plans out of bounds: {err}" ) )
177214 }
178215
179216 /// Get the compilation context for a query
180217 #[ allow( dead_code) ]
181- pub fn get_query_context ( & self , module_idx : u32 , query_idx : u32 ) -> Option < & ScopeContext > {
218+ pub fn get_query_context (
219+ & self ,
220+ module_idx : u32 ,
221+ query_idx : u32 ,
222+ ) -> LookupResult < Option < & ScopeContext > > {
182223 self . query_contexts . get_checked ( module_idx, query_idx)
183224 }
184225
185226 /// Get the binding plan for an expression
186- pub fn get_expr_binding_plan ( & self , module_idx : u32 , expr_idx : u32 ) -> Option < & BindingPlan > {
227+ pub fn get_expr_binding_plan (
228+ & self ,
229+ module_idx : u32 ,
230+ expr_idx : u32 ,
231+ ) -> LookupResult < Option < & BindingPlan > > {
187232 self . expr_binding_plans . get_checked ( module_idx, expr_idx)
188233 }
189234
@@ -275,14 +320,18 @@ impl LoopHoister {
275320 Ok ( self . lookup )
276321 }
277322
278- fn create_scope_context ( & self , module_idx : u32 ) -> ScopeContext {
323+ fn create_scope_context ( & self , module_idx : u32 ) -> Result < ScopeContext > {
279324 let mut context = ScopeContext :: new ( ) ;
280325
281- if let Some ( globals) = self . module_globals . get_checked ( module_idx, 0 ) {
326+ if let Some ( globals) = self
327+ . module_globals
328+ . get_checked ( module_idx, 0 )
329+ . map_err ( |err| anyhow ! ( "module_globals out of bounds: {err}" ) ) ?
330+ {
282331 context. module_globals = Some ( globals. clone ( ) ) ;
283332 }
284333
285- context
334+ Ok ( context)
286335 }
287336
288337 /// Populate loop hoisting information for all modules, with extra capacity
@@ -309,7 +358,8 @@ impl LoopHoister {
309358 self . lookup . ensure_expr_capacity ( last_module_idx + i, 0 ) ;
310359 self . module_globals . ensure_capacity ( last_module_idx + i, 0 ) ;
311360 self . module_globals
312- . set ( last_module_idx + i, 0 , crate :: Rc :: new ( BTreeSet :: new ( ) ) ) ;
361+ . set_checked ( last_module_idx + i, 0 , crate :: Rc :: new ( BTreeSet :: new ( ) ) )
362+ . map_err ( |err| anyhow ! ( "module_globals out of bounds: {err}" ) ) ?;
313363 }
314364 Ok ( self . lookup )
315365 }
@@ -360,10 +410,11 @@ impl LoopHoister {
360410 reserved_globals. insert ( "data" . to_string ( ) ) ;
361411 reserved_globals. insert ( "input" . to_string ( ) ) ;
362412 self . module_globals
363- . set ( module_idx, 0 , crate :: Rc :: new ( reserved_globals) ) ;
413+ . set_checked ( module_idx, 0 , crate :: Rc :: new ( reserved_globals) )
414+ . map_err ( |err| anyhow ! ( "module_globals out of bounds: {err}" ) ) ?;
364415
365416 // Populate the query with default context
366- let context = self . create_scope_context ( module_idx) ;
417+ let context = self . create_scope_context ( module_idx) ? ;
367418 self . lookup . ensure_query_capacity ( module_idx, query. qidx ) ;
368419 self . populate_query ( module_idx, query, & context) ?;
369420 Ok ( ( ) )
@@ -374,7 +425,7 @@ impl LoopHoister {
374425 match rule {
375426 Rule :: Spec { head, bodies, .. } => {
376427 // Create a context for this rule
377- let mut context = self . create_scope_context ( module_idx) ;
428+ let mut context = self . create_scope_context ( module_idx) ? ;
378429
379430 // Bind function parameters if this is a function rule
380431 if let RuleHead :: Func { args, .. } = head {
@@ -396,7 +447,7 @@ impl LoopHoister {
396447 module_idx,
397448 expr_idx,
398449 binding_plan,
399- ) ;
450+ ) ? ;
400451 }
401452 Err ( err) => return Err ( map_binding_error ( err) ) ,
402453 }
@@ -454,7 +505,7 @@ impl LoopHoister {
454505 module_idx,
455506 body. query . qidx ,
456507 populated_body_context. clone ( ) ,
457- ) ;
508+ ) ? ;
458509
459510 // Process the key expression if present
460511 if let Some ( ref key) = key_expr {
@@ -497,7 +548,7 @@ impl LoopHoister {
497548 }
498549 Rule :: Default { value, .. } => {
499550 // For default rules, just process the value expression
500- let context = self . create_scope_context ( module_idx) ;
551+ let context = self . create_scope_context ( module_idx) ? ;
501552 self . populate_output_expr ( module_idx, value, & context) ?;
502553 }
503554 }
@@ -518,7 +569,11 @@ impl LoopHoister {
518569
519570 // Get the scheduled order if available
520571 let stmt_order: Vec < usize > = if let Some ( ref schedule) = self . schedule {
521- if let Some ( query_schedule) = schedule. queries . get ( module_idx, query. qidx ) {
572+ if let Some ( query_schedule) = schedule
573+ . queries
574+ . get_checked ( module_idx, query. qidx )
575+ . map_err ( |err| anyhow ! ( "schedule out of bounds: {err}" ) ) ?
576+ {
522577 query_schedule
523578 . order
524579 . iter ( )
@@ -566,7 +621,8 @@ impl LoopHoister {
566621 }
567622
568623 self . lookup . ensure_statement_capacity ( module_idx, stmt_idx) ;
569- self . lookup . set_statement_loops ( module_idx, stmt_idx, loops) ;
624+ self . lookup
625+ . set_statement_loops ( module_idx, stmt_idx, loops) ?;
570626
571627 Ok ( ( ) )
572628 }
@@ -596,7 +652,7 @@ impl LoopHoister {
596652 self . lookup . ensure_expr_capacity ( module_idx, expr_idx) ;
597653 Self :: bind_vars_from_plan_to_context ( & binding_plan, context) ;
598654 self . lookup
599- . set_expr_binding_plan ( module_idx, expr_idx, binding_plan) ;
655+ . set_expr_binding_plan ( module_idx, expr_idx, binding_plan) ? ;
600656
601657 if let Some ( key_expr) = key {
602658 self . analyze_expr ( module_idx, key_expr, context, loops) ?;
@@ -615,7 +671,7 @@ impl LoopHoister {
615671 self . populate_query ( module_idx, query. as_ref ( ) , & every_context) ?;
616672 self . lookup . ensure_query_capacity ( module_idx, query. qidx ) ;
617673 self . lookup
618- . set_query_context ( module_idx, query. qidx , populated_context) ;
674+ . set_query_context ( module_idx, query. qidx , populated_context) ? ;
619675 }
620676 NotExpr { expr, .. } => {
621677 self . analyze_expr ( module_idx, expr, context, loops) ?;
@@ -663,7 +719,7 @@ impl LoopHoister {
663719 self . populate_query ( module_idx, query. as_ref ( ) , & compr_context) ?;
664720 self . lookup . ensure_query_capacity ( module_idx, query. qidx ) ;
665721 self . lookup
666- . set_query_context ( module_idx, query. qidx , populated_context. clone ( ) ) ;
722+ . set_query_context ( module_idx, query. qidx , populated_context. clone ( ) ) ? ;
667723 self . populate_output_expr_with_context ( module_idx, term, & populated_context) ?;
668724 }
669725 E :: ObjectCompr {
@@ -678,7 +734,7 @@ impl LoopHoister {
678734 self . populate_query ( module_idx, query. as_ref ( ) , & compr_context) ?;
679735 self . lookup . ensure_query_capacity ( module_idx, query. qidx ) ;
680736 self . lookup
681- . set_query_context ( module_idx, query. qidx , populated_context. clone ( ) ) ;
737+ . set_query_context ( module_idx, query. qidx , populated_context. clone ( ) ) ? ;
682738 self . populate_output_expr_with_context ( module_idx, key, & populated_context) ?;
683739 self . populate_output_expr_with_context ( module_idx, value, & populated_context) ?;
684740 }
@@ -721,8 +777,11 @@ impl LoopHoister {
721777 // Immediately bind variables from the plan to context
722778 Self :: bind_vars_from_plan_to_context ( & binding_plan, context) ;
723779
724- self . lookup
725- . set_expr_binding_plan ( module_idx, expr_idx, binding_plan) ;
780+ self . lookup . set_expr_binding_plan (
781+ module_idx,
782+ expr_idx,
783+ binding_plan,
784+ ) ?;
726785 }
727786 Err ( err) => return Err ( map_binding_error ( err) ) ,
728787 }
@@ -746,8 +805,11 @@ impl LoopHoister {
746805 let expr_idx = index. as_ref ( ) . eidx ( ) ;
747806 self . lookup . ensure_expr_capacity ( module_idx, expr_idx) ;
748807 Self :: bind_vars_from_plan_to_context ( & binding_plan, context) ;
749- self . lookup
750- . set_expr_binding_plan ( module_idx, expr_idx, binding_plan) ;
808+ self . lookup . set_expr_binding_plan (
809+ module_idx,
810+ expr_idx,
811+ binding_plan,
812+ ) ?;
751813 }
752814 Err ( err) => return Err ( map_binding_error ( err) ) ,
753815 }
@@ -780,7 +842,7 @@ impl LoopHoister {
780842 self . lookup . ensure_expr_capacity ( module_idx, expr_idx) ;
781843 Self :: bind_vars_from_plan_to_context ( & binding_plan, context) ;
782844 self . lookup
783- . set_expr_binding_plan ( module_idx, expr_idx, binding_plan) ;
845+ . set_expr_binding_plan ( module_idx, expr_idx, binding_plan) ? ;
784846
785847 self . analyze_expr ( module_idx, lhs, context, loops) ?;
786848 self . analyze_expr ( module_idx, rhs, context, loops) ?;
@@ -857,7 +919,7 @@ impl LoopHoister {
857919
858920 let expr_idx = expr. as_ref ( ) . eidx ( ) ;
859921 self . lookup . ensure_expr_capacity ( module_idx, expr_idx) ;
860- self . lookup . set_expr_loops ( module_idx, expr_idx, loops) ;
922+ self . lookup . set_expr_loops ( module_idx, expr_idx, loops) ? ;
861923
862924 Ok ( ( ) )
863925 }
0 commit comments