# simple example of a global variable invariant:
# a timer that counts down to zero

time = 0
#PREMISES FOR ATTACHED PROOF, IF ANY: 
# (time == 0)

# we want to maintain true this invariant property:
"""{ globalinvOK   time >= 0 }"""
#PREMISES FOR NEXT LINE: 
# (time >= 0)

# the checker  verifies that the invariant holds true HERE, on initialization.

# the function below can use the invariant, and the function
# must ensure that the invariant holds on exit:

def tick() :
    """{ pre  True 
         post ans == time
         return ans
    }"""
    global time 
    #PREMISES FOR NEXT LINE: 
    # True
    # (time >= 0)
    # as needed, we can introduce the globalinv  into a proof:
    """{ 1.OK  time >= 0         premise   }"""
    #PREMISES FOR NEXT LINE: 
    # (time >= 0)
    if time != 0 :
        #PREMISES FOR THEN-ARM: 
        # (time != 0)
        # (time >= 0)
        time = time - 1
        #PREMISES FOR ATTACHED PROOF, IF ANY: 
        # (time == (time_old - 1))
        # (time_old != 0)
        # (time_old >= 0)
        """{ 1.OK time_old != 0     premise
             2.OK time_old >= 0     premise
             3.OK time_old > 0      algebra 1 2
             4.OK time == time_old - 1    premise
             5.OK time >= 0         algebra 3 4
        }"""
        #PREMISES FOR NEXT LINE: 
        # (time >= 0)
    else :
        #PREMISES FOR ELSE-ARM: 
        # not (time != 0)
        # (time >= 0)
        print "RING RING RING"
        #PREMISES FOR NEXT LINE: 
        # not (time != 0)
        # (time >= 0)
        """{ 1.OK  time >= 0     premise  }"""
        #PREMISES FOR NEXT LINE: 
        # (time >= 0)
    #PREMISES FOR NEXT LINE: 
    # (time >= 0)
    ans = time
    #PREMISES FOR ATTACHED PROOF, IF ANY: 
    # (ans == time)
    # (time >= 0)
    #PREMISES FOR NEXT LINE: 
    # (ans == time)
    # (time >= 0)
    # POSTCONDITION AND ALL GLOBAL INVARIANTS VERIFIED AT POINT OF RETURN
    # we have proved enough facts that the checker can verify that the
    # invariant holds true and so does the function's postcondition
    return ans
    #PREMISES FOR NEXT LINE: 
    # (ans == time)
    # (time >= 0)
    # POSTCONDITION AND ALL GLOBAL INVARIANTS VERIFIED AT END OF FUNCTION
#PREMISES FOR NEXT LINE: 
# (time >= 0)


def init(starttime) :
    """{ pre  starttime > 0
         post True
    }"""
    global time
    #PREMISES FOR NEXT LINE: 
    # (starttime > 0)
    # (time >= 0)
    time = starttime
    #PREMISES FOR ATTACHED PROOF, IF ANY: 
    # (time == starttime)
    # (starttime > 0)
    # (time_old >= 0)
    #PREMISES FOR NEXT LINE: 
    # (time == starttime)
    # (starttime > 0)
    # POSTCONDITION AND ALL GLOBAL INVARIANTS VERIFIED AT END OF FUNCTION
#PREMISES FOR NEXT LINE: 
# (time >= 0)
    # the checker easily verifies the global invariant:  time >= 0


# Driver code starts here: run the timer

# invariant holds true
novar = init(10)
#PREMISES FOR ATTACHED PROOF, IF ANY: 
# True
# (time_old >= 0)
#PREMISES FOR NEXT LINE: 
# invariant holds true
a = tick()
#PREMISES FOR ATTACHED PROOF, IF ANY: 
# (a == time)
#PREMISES FOR NEXT LINE: 
# (a == time)
# invariant holds true
a = tick()
#PREMISES FOR ATTACHED PROOF, IF ANY: 
# (a == time)
# (a_old == time_old)
#PREMISES FOR NEXT LINE: 
# (a == time)
# invariant holds true
a = tick()
#PREMISES FOR ATTACHED PROOF, IF ANY: 
# (a == time)
# (a_old == time_old)
#PREMISES FOR NEXT LINE: 
# (a == time)
# invariant holds true