
# CODE THAT KEEPS TRACK OF THE COINS IN A TOY BANK:

# module DimesBank {

# fields in module:
dimes = 0
money = 0
# we want the module to maintain true this invariant property:
"""{ globalinv  money == dimes * 10  }"""

# the checker  verifies that the invariant holds true HERE, on initialization.

# the method/function below can use the invariant, and the function
# must ensure that the invariant holds on exit:
def handleCoinInsertion(howmany) :
    """handles the insertion of  howmany  dimes into the bank:"""
    """{ pre   howmany >= 0 
         post  True        # the function enforces the invariant, that's it.
    }"""
    global dimes, money
    # we can introduce the invariant as a premise as needed:
    """{ 1.  money == dimes * 10      premise   }"""
    dimes = dimes + howmany
    """{ 1.  money == dimes_old * 10                premise
         2.  dimes == dimes_old + howmany           premise
         4.  money + (howmany * 10) == dimes * 10   algebra  1 2
    }"""
    # invariant is broken here, but the next command restores it:
    money = money + (howmany * 10)
    """{ 1.  money_old + (howmany * 10) == dimes * 10    premise
         2.  money == money_old + (howmany * 10)         premise
         3.  money == dimes * 10                         subst 2 1 
    }"""
    # the checker verifies here that the invariant is true again.
    
# } END MODULE


# the following would be in a component that imports (uses) the module:

# throughout every line of the following code, the invariant is holding true:
coins = readInt("press button and insert your coins!")
assert coins > 0
novar = handleCoinInsertion(coins)
print money


