.include common

overflow( buffer:node, where:node )

static_sized_buffer( buffer:node, size:number )
buffer_indexed( buffer:node, index:node, where:node )
unchecked_path( index:node, size:number, \
                start:node, si:number, \
                end:node, ei:number)
loop_or_if( n:node )

#our main query
overflow( buffer, where ) :- \
    static_sized_buffer( buffer, size ), \
    buffer_indexed( buffer, index, where ), \
    iname( start, _, index, _ ), \
    unchecked_path( index, size, start, 0, where, 0 ).

static_sized_buffer( buffer, size ) :- \
  varD( var ), \
  iname( iname, _ , buffer, t ), \
  parent( var, iname ), \
  arrayT(t,_, sizeexp ), \
  intL( sizeexp, size).

buffer_indexed( buffer, index, where) :- \
   arraySubscriptE( where, rs, ls ), \
   varE( rs, buffer ), \
   varE( ls, index ).

#We've hit the end!
unchecked_path( _, _, start, si, end, ei ) :- \
    start=end, si=ei.


#no conditional, no check
unchecked_path( index, size, start, si, end, ei ) :- \
    !loop_or_if(start), \
    cfgNext( start, si, next, ni ), \
    unchecked_path( index, size, next, ni, end, ei ).


#into conditional of if or loop
unchecked_path( index, size, start, si, end, ei ) :- \
    si = 0, \
    loop_or_if( start ), \
    cfgNext( start, si, next, ni ), \
    unchecked_path( index, size, next, ni, end, ei ).
 
#if the condition is true, the index is checked
checkedTrue( cond:node, index:node, size:number )
#if the condition is false, the index is checked
checkedFalse( cond:node, index:node, size:number )

#if with true branch unchecked
unchecked_path( index, size, start, si, end, ei ) :- \
    si = 1, \
    ifS( start, cond, next, _ ), \
    !checkedTrue( cond, index, size ), \
    cfgNext( start, si, next, ni ), \
    unchecked_path( index, size, next, ni, end, ei ).

#if with false branch unchecked
unchecked_path( index, size, start, si, end, ei ) :- \
    si = 1, \
    ifS( start, cond, _, next ), \
    !checkedFalse( cond, index, size ), \
    cfgNext( start, si, next, ni ), \
    unchecked_path( index, size, next, ni, end, ei ).


#in loop
unchecked_path( index, size, start, si, end, ei ) :- \
    si = 1, \
    loop( start, cond, _ ), \
    !checkedTrue( cond, index, size ), \
    cfgNext(start, si, next, ni ), \
    unchecked_path( index, size, next, ni, end, ei ).

#after if or loop
unchecked_path( index, size, start, si, end, ei ) :- \
    si = 2, \
    loop_or_if(start), \
    cfgNext( start, si, next, ni ), \
    unchecked_path( index, size, next, ni, end, ei ).

loop_or_if( n ) :- ifS( n, _, _, _ ).
loop_or_if( n ) :- loop( n, _, _ ).

checkedTrue( c, i, s ) :- \
    anc(c,ce), leqE( ce, l, r ), varE( l, i ), intL( r, b ), b < s.
checkedTrue( c, i, s ) :- \
    anc(c,ce), geqE( ce, l, r ), varE( r, i ), intL( l, b ), b < s.
checkedFalse( c, i, s ) :- \
    anc(c,ce), gtE( ce, l, r ), varE( l, i ), intL( r, b ), b < s.
checkedFalse( c, i, s ) :- \
    anc(c,ce), ltE( ce, l, r ), varE( r, i ), intL( l, b ), b < s.


overflow( buffer, where )?

