/**
 **/
package test.runtime;

import ovm.core.repository.Selector;
import ovm.core.domain.Blueprint;
import ovm.core.domain.Oop;
import ovm.core.domain.Type;
import ovm.core.repository.RepositoryClass;
import ovm.core.repository.RepositoryMember;
import ovm.core.repository.UnboundSelector;
import ovm.core.services.memory.VM_Address;
import s3.util.PragmaHierarchy;
import s3.util.PragmaSquawk;
import s3.util.PragmaTransformCallsiteIR;
import test.common.TestBase;

/**
 * Tests the runtime evaluation of pragmas.
 * During image-build, the rewriter should squawk three times: while rewriting
 * the bodies of b() and c(), and while rewriting the invokevirtual of c() in
 * method a(). At run time, the iteration over the methods of this class should
 * count two methods (b and c) that declare PragmaSquawk.
 * @author Chapman Flack
 **/
public class TestPragma
    extends TestBase {

    public TestPragma() {
	super("Pragma");
    }

    public void run() {
	testBooleanPragma();
	testHierarchicalPragma();
	testInlineSubstituteBytecode();
    }
    
    public void testBooleanPragma() {
	setModule("boolean pragma");
	
	VM_Address me = VM_Address.fromObject( this);
//	Oop meAsAnOop = me.asOop();            // hardcoded type, old way
  	Oop meAsAnOop = (Oop)me.asAnyObject(); // general soln, now works
	Blueprint bp = meAsAnOop.getBlueprint();
	
	Type.Scalar ts = bp.getType().asScalar();
	RepositoryClass rc = ts.getRepositoryClass();
	RepositoryMember.Method[] methods = rc.getInstanceMethods();
	int squawks = 0;
	for ( int i = 0; i < methods.length; ++i ) {
	  UnboundSelector.Method us = methods[i].getUnboundSelector();
	  Selector.Method ms = Selector.Method.make( us, ts.getName());
	  if ( PragmaSquawk.declaredBy( ms, bp) ) {
	    ++ squawks;
	  }
	}
	check_condition( squawks == 2, "Squawk miscount");
    }
    
    public void testHierarchicalPragma() {
	setModule("hierarchical pragma");
	Blueprint bp = VM_Address.fromObject( this).asOop().getBlueprint();
	Type.Scalar ts = bp.getType().asScalar();
	RepositoryClass rc = ts.getRepositoryClass();
	RepositoryMember.Method[] methods = rc.getInstanceMethods();
	int hierks = 0;
	for ( int i = 0; i < methods.length; ++i ) {
	  UnboundSelector.Method us = methods[i].getUnboundSelector();
	  Selector.Method ms = Selector.Method.make( us, ts.getName());
	  String cookie = (String)PragmaHierarchy.descendantDeclaredBy( ms, bp);
	  if ( cookie != null ) {
	    ++ hierks;
	   // p( ms.toString());
	   // p( ": ");
	   // p( cookie);
	   // p( "\n");
	  }
	}
	check_condition( hierks == 3, "Hierarchical pragma miscount");
    }
    
    public void testInlineSubstituteBytecode() {
      	setModule("PragmaTransformCallsiteIR");
	check_condition( g(1) == 1, "Method g not substituted");
    }
    
    public void a() { c(); d(); e(); f(); }
    
    public void b() throws PragmaSquawk { }
    
    void c() throws PragmaSquawk { }
    
    void d() throws PragmaHierarchy { }
    void e() throws PragmaHierarchy.Foo { }
    void f() throws PragmaHierarchy.Bar { }
    
    int g( int i) throws PragmaTransformCallsiteIR.BCnothing { return 2; }
    
} // end of TestPragma
