Skip to content

Commit

Permalink
Add loop bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Oct 15, 2024
1 parent ac2ab6f commit e0426ea
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 9 deletions.
3 changes: 3 additions & 0 deletions src/analyzer/scope/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ pub struct BlockContext {

pub inside_async: bool,

pub loop_bounds: (u32, u32),

pub for_loop_init_bounds: (u32, u32),

/* Effects for pipe var, if applicable */
Expand Down Expand Up @@ -205,6 +207,7 @@ impl BlockContext {
parent_conflicting_clause_vars: FxHashSet::default(),
allow_taints: true,
inside_async: false,
loop_bounds: (0, 0),
for_loop_init_bounds: (0, 0),

pipe_var_effects: EFFECT_PURE,
Expand Down
13 changes: 9 additions & 4 deletions src/analyzer/stmt/do_analyzer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::BTreeMap;

use hakana_algebra::Clause;
use oxidized::aast;
use oxidized::{aast, pos::Pos};
use rustc_hash::{FxHashMap, FxHashSet};

use crate::{
Expand All @@ -21,6 +21,7 @@ use super::{
pub(crate) fn analyze(
statements_analyzer: &StatementsAnalyzer,
stmt: (&aast::Block<(), ()>, &aast::Expr<(), ()>),
pos: &Pos,
analysis_data: &mut FunctionAnalysisData,
context: &mut BlockContext,
) -> Result<(), AnalysisError> {
Expand Down Expand Up @@ -72,6 +73,10 @@ pub(crate) fn analyze(
));
}

let prev_loop_bounds = do_context.loop_bounds;

do_context.loop_bounds = (pos.start_offset() as u32, pos.end_offset() as u32);

let mut inner_loop_context = loop_analyzer::analyze(
statements_analyzer,
&stmt.0 .0,
Expand All @@ -85,6 +90,8 @@ pub(crate) fn analyze(
true,
)?;

do_context.loop_bounds = prev_loop_bounds;

let clauses_to_simplify = {
let mut c = context
.clauses
Expand Down Expand Up @@ -120,9 +127,7 @@ pub(crate) fn analyze(
}

for (var_id, var_type) in inner_loop_context.locals {
context
.locals
.insert(var_id.clone(), var_type.clone());
context.locals.insert(var_id.clone(), var_type.clone());
}

Ok(())
Expand Down
5 changes: 5 additions & 0 deletions src/analyzer/stmt/for_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pub(crate) fn analyze(
for_context.inside_loop = true;
for_context.break_types.push(BreakContext::Loop);

let prev_loop_bounds = for_context.loop_bounds;
for_context.loop_bounds = (pos.start_offset() as u32, pos.end_offset() as u32);

loop_analyzer::analyze(
statements_analyzer,
&stmt.3 .0,
Expand All @@ -63,6 +66,8 @@ pub(crate) fn analyze(
while_true,
)?;

for_context.loop_bounds = prev_loop_bounds;

// theoretically we could also port over always_enters_loop logic from Psalm here
// but I'm not sure that would be massively useful

Expand Down
5 changes: 5 additions & 0 deletions src/analyzer/stmt/foreach_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ pub(crate) fn analyze(
foreach_context.for_loop_init_bounds = (0, 0);
foreach_context.inside_loop_exprs = false;

let prev_loop_bounds = foreach_context.loop_bounds;
foreach_context.loop_bounds = (pos.start_offset() as u32, pos.end_offset() as u32);

loop_analyzer::analyze(
statements_analyzer,
&stmt.2 .0,
Expand All @@ -155,6 +158,8 @@ pub(crate) fn analyze(
always_non_empty_array,
)?;

foreach_context.loop_bounds = prev_loop_bounds;

// todo do we need to remove the loop scope from analysis_data here? unsure

Ok(())
Expand Down
14 changes: 9 additions & 5 deletions src/analyzer/stmt/while_analyzer.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use super::{control_analyzer::BreakContext, loop_analyzer};
use crate::{
function_analysis_data::FunctionAnalysisData,
scope_analyzer::ScopeAnalyzer,
scope::{control_action::ControlAction, loop_scope::LoopScope, BlockContext},
scope_analyzer::ScopeAnalyzer,
statements_analyzer::StatementsAnalyzer,
stmt_analyzer::AnalysisError,
};
use oxidized::{aast, ast_defs};
use oxidized::{aast, ast_defs, pos::Pos};
use std::rc::Rc;

pub(crate) fn analyze(
statements_analyzer: &StatementsAnalyzer,
stmt: (&aast::Expr<(), ()>, &aast::Block<(), ()>),
pos: &Pos,
analysis_data: &mut FunctionAnalysisData,
context: &mut BlockContext,
) -> Result<(), AnalysisError> {
Expand All @@ -38,6 +39,9 @@ pub(crate) fn analyze(
false
};

let prev_loop_bounds = while_context.loop_bounds;
while_context.loop_bounds = (pos.start_offset() as u32, pos.end_offset() as u32);

let inner_loop_context = loop_analyzer::analyze(
statements_analyzer,
&stmt.1 .0,
Expand All @@ -51,6 +55,8 @@ pub(crate) fn analyze(
always_enters_loop,
)?;

while_context.loop_bounds = prev_loop_bounds;

let can_leave_loop = !while_true || loop_scope.final_actions.contains(&ControlAction::Break);

if always_enters_loop {
Expand Down Expand Up @@ -79,9 +85,7 @@ pub(crate) fn analyze(
);
}
} else {
context
.locals
.insert(var_id.clone(), var_type.clone());
context.locals.insert(var_id.clone(), var_type.clone());
}
}
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/analyzer/stmt_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub(crate) fn analyze(
while_analyzer::analyze(
statements_analyzer,
(&boxed.0, &boxed.1),
&stmt.0,
analysis_data,
context,
)?;
Expand All @@ -108,6 +109,7 @@ pub(crate) fn analyze(
do_analyzer::analyze(
statements_analyzer,
(&boxed.0, &boxed.1),
&stmt.0,
analysis_data,
context,
)?;
Expand Down

0 comments on commit e0426ea

Please sign in to comment.