#!/usr/bin/ruby -w
# first draft for Design By Contract class, glarked from ruby-talk.

module DBC
  class DBCError          < StandardError ; end
  class DBCPreError       < DBCError      ; end
  class DBCPostError      < DBCError      ; end
  class DBCInvariantError < DBCError      ; end

  def pre
    raise DBCPreError unless yield
  end

  def post(klass, method, invariant)
    raise DBCPostError unless yield
    if defined? invariant and
        klass.public_instance_methods(false).include?(method) then
      raise DBCInvariantError unless invariant()
    end
  end
end

include DBC
class Foo
  #@a
  def invariant
    @a != 3
  end
  def initialize
    @a = 0      
  end
  def bar(b)
    pre { b != 1 }
    @a += b       
    print "@a = ", @a, "\n"
    post(Foo, "bar", self) { @a != 2 }
  end
end

for i in (0..4) do
  print "\nTesting foo.bar(#{i})\n"
  foo = Foo.new
  begin
    foo.bar(i)
  rescue DBCPreError
    print "DBCPreError happened as expected\n"
  rescue DBCPostError
    print "DBCPostError happened as expected\n"
  rescue DBCInvariantError
    print "DBCInvariantError happened as expected\n"
  rescue Exception
    print "Some unexpected error happened\n"
  end  
end
