Package xscript.runtime.instruction

Source Code of xscript.runtime.instruction.XInstructionInvokeSpecial

package xscript.runtime.instruction;

import java.io.IOException;

import xscript.runtime.XChecks;
import xscript.runtime.XModifier;
import xscript.runtime.XRuntimeException;
import xscript.runtime.XVirtualMachine;
import xscript.runtime.clazz.XClass;
import xscript.runtime.clazz.XInputStream;
import xscript.runtime.clazz.XOutputStream;
import xscript.runtime.clazz.XPrimitive;
import xscript.runtime.genericclass.XClassPtr;
import xscript.runtime.genericclass.XGenericClass;
import xscript.runtime.genericclass.XGenericMethodProviderImp;
import xscript.runtime.method.XMethod;
import xscript.runtime.object.XObject;
import xscript.runtime.threads.XMethodExecutor;
import xscript.runtime.threads.XThread;

public class XInstructionInvokeSpecial extends XInstruction {

  private String className;
  private String methodName;
  private String[] methodParams;
  private String methodReturn;
  private XClassPtr[] generics;
  private XMethod method;
 
  public XInstructionInvokeSpecial(XMethod method, XClassPtr[] generics){
    className = method.getDeclaringClass().getName();
    methodName = method.getSimpleName();
    methodParams = method.getMethodParamNames();
    methodReturn = method.getMethodReturnName();
    this.generics = generics;
    this.method = method;
    if(generics==null){
      if(method.getGenericParams()!=0)
        throw new XRuntimeException("Can't create a generic method %s without generic params, need %s generic params", method, method.getGenericParams());
    }else if(generics.length!=method.getGenericParams()){
      throw new XRuntimeException("Can't create a generic method %s with %s generic params, need %s generic params", method, generics.length, method.getGenericParams());
    }
    if(XModifier.isStatic(method.getModifier())){
      throw new XRuntimeException("Method %s is static", method);
    }
  }
 
  public XInstructionInvokeSpecial(XInputStream inputStream) throws IOException{
    className = inputStream.readUTF();
    methodName = inputStream.readUTF();
    methodParams = new String[inputStream.readUnsignedByte()];
    for(int i=0; i<methodParams.length; i++){
      methodParams[i] = inputStream.readUTF();
    }
    methodReturn = inputStream.readUTF();
    generics = new XClassPtr[inputStream.readUnsignedByte()];
    for(int i=0; i<generics.length; i++){
      generics[i] = XClassPtr.load(inputStream);
    }
  }
 
  @Override
  public void run(XVirtualMachine vm, XThread thread, XMethodExecutor methodExecutor) {
    resolve(vm, methodExecutor);
    final XGenericClass[] solvedGenerics = new XGenericClass[generics.length];
    for(int i=0; i<solvedGenerics.length; i++){
      solvedGenerics[i] = generics[i].getXClass(vm, methodExecutor.getDeclaringClass(), methodExecutor);
    }
    XGenericClass[] paramTypes = method.getParams(null, new XGenericMethodProviderImp(method, solvedGenerics));
    long[] params = new long[paramTypes.length+1];
    for(int i=params.length-1; i>0; i++){
      int pID = XPrimitive.getPrimitiveID(paramTypes[i-1].getXClass());
      params[i] = methodExecutor.pop(pID);
      if(pID==XPrimitive.OBJECT){
        XObject obj = vm.getObjectProvider().getObject(params[i]);
        XChecks.checkCast(obj.getXClass(), paramTypes[i-1]);
      }
    }
    params[0] = methodExecutor.oPop();
    XObject _this = vm.getObjectProvider().getObject(params[0]);
    method.getMethod(_this);
    thread.call(method, solvedGenerics, params);
  }

  private void resolve(XVirtualMachine vm, XMethodExecutor methodExecutor){
    if(method==null){
      XClass xClass = vm.getClassProvider().getXClass(className);
      method = xClass.getMethod(methodName, methodParams, methodReturn);
      XChecks.checkAccess(methodExecutor.getMethod().getDeclaringClass(), method);
      if(generics==null){
        if(method.getGenericParams()!=0)
          throw new XRuntimeException("Can't create a generic method %s without generic params, need %s generic params", method, method.getGenericParams());
      }else if(generics.length!=method.getGenericParams()){
        throw new XRuntimeException("Can't create a generic method %s with %s generic params, need %s generic params", method, generics.length, method.getGenericParams());
      }
      if(XModifier.isStatic(method.getModifier())){
        throw new XRuntimeException("Method %s is static", method);
      }
    }
  }
 
  public XMethod getMethod(XVirtualMachine vm){
    if(method==null){
      XClass xClass = vm.getClassProvider().getXClass(className);
      return xClass.getMethod(methodName, methodParams, methodReturn);
    }
    return method;
  }
 
  @Override
  protected void save(XOutputStream outputStream) throws IOException {
    outputStream.writeUTF(className);
    outputStream.writeUTF(methodName);
    outputStream.writeByte(methodParams.length);
    for(int i=0; i<methodParams.length; i++){
      outputStream.writeUTF(methodParams[i]);
    }
    outputStream.writeUTF(methodReturn);
    outputStream.writeByte(generics.length);
    for(int i=0; i<generics.length; i++){
      generics[i].save(outputStream);
    }
  }

  @Override
  public String getSource() {
    String s = "(";
    if(methodParams.length>0){
      s += methodParams[0];
      for(int i=0; i<methodParams.length; i++){
        s += ", "+methodParams[i];
      }
      s += ")";
    }
    s += methodReturn;
    return "invd "+className+"."+methodName+s;
  }

}
TOP

Related Classes of xscript.runtime.instruction.XInstructionInvokeSpecial

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.