This exercise requires you to modify the dynamic semantics of typed KOOL
into a profiling tool that outputs how many object instances of each class
have been created and how many times each method has been called durig the
execution of a program.  For example, consider the KOOL program

class C1 {
  void C1() {}
  int m1() { return 1; }
  int m2() { return m1(); }
}

class C2 extends C1 {
  void C2() {}
  int m1() { return 2; }
}

class Main {
  void Main() {
    C1 o1 = new C1();
    C2 o2 = new C2();
    print(o1.m1(), " ", o1.m2(), " ", o2.m1(), " ", o2.m2(), "\n");
  }
}

Normally, this program outputs "1 1 2 2".  However, with the modified
semantics, it will yield the following output:

1 1 2 2

==========
Statistics
==========

Objects created:
   Main |-> 1
   C1 |-> 1
   C2 |-> 1

Methods invoked:
   Main.Main |-> 1
   C1.C1 |-> 1
   C1.m1 |-> 2
   C1.m2 |-> 2
   C2.C2 |-> 1
   C2.m1 |-> 2

The tests folder contains the new outputs of all the KOOL programs
considered so far, plus more.  The order in which you output the classes
or the methods in the two statistics is irrelevant, so do not worry about it.
