{
  ex4.s

  Contents:

     1. a normal class A
     2. a shell class C whose allowed set contains A. Class C defines
        a method interceptAll.

  Tests:
     1. the unoptimized version of method interceptAll of shell class C.
        Read comments in this method for more information.
     2. message sends to "object" in shell and extension classes.

  }

class A
  private:
    var i :  integer;
  public:
   proc get() : integer
     begin
     write(100);
     return i;
     end
   proc put( NewI : integer )
     begin
     i = NewI;
     write(200);
     end
endclass


shell class C(A)
  private:
    var k : integer;
  public:
    proc interceptAll( mi : Method; vetArg : array(Object)[] ) : Object
        var obj : Object;
            v   : array(Object)[];
            new_mi : Method;
      begin
        { the three assignments below prevents the compiler from
          doing any otimizations regarding:
             1. the message send to mi
             2. the allocation of array vetArg in the stack. The compiler
                creates a method for C for each A method. This method
                calls interceptAll. Then, it needs an array vetArg. If no
                assignments from vetArg exists in this method, vetArg
                can be allocated in the stack. Otherwise, it must be
                dynamically allocated, which is much slower.
          }
      v = vetArg;
      new_mi = mi;
      mi = new_mi;

      write(mi.getMethodNumber());
      obj = mi.invoke(self, vetArg);
      return obj;
      end
endclass



class Program
  public:
    proc run()
        var a : A;
      begin
      a = A.new();
      a.put(4);
      if Reflect.attachShell(a, C.new()) == 0
      then
        a.put(5);
        if Reflect.removeShell(a) == 0
        then
          a.put(5);
        endif
      endif
      end
endclass


