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.XField;
import xscript.runtime.clazz.XInputStream;
import xscript.runtime.clazz.XOutputStream;
import xscript.runtime.clazz.XPrimitive;
import xscript.runtime.genericclass.XClassPtr;
import xscript.runtime.threads.XMethodExecutor;
import xscript.runtime.threads.XThread;
public class XInstructionSetStaticField extends XInstruction {
private String className;
private String fieldName;
private XClassPtr fieldType;
private XField field;
public XInstructionSetStaticField(XField field){
className = field.getDeclaringClass().getName();
fieldName = field.getSimpleName();
fieldType = field.getType();
this.field = field;
}
public XInstructionSetStaticField(XInputStream inputStream) throws IOException{
className = inputStream.readUTF();
fieldName = inputStream.readUTF();
fieldType = XClassPtr.load(inputStream);
}
@Override
public void run(XVirtualMachine vm, XThread thread, XMethodExecutor methodExecutor) {
resolve(vm, methodExecutor);
long value = methodExecutor.pop(getPrimitiveID(vm));
if(XModifier.isFinal(field.getModifier())){
if(methodExecutor.getMethod().getSimpleName().equals("<staticInit>") && methodExecutor.getMethod().getDeclaringClass()==field.getDeclaringClass()){
field.finalSet(null, value);
}else{
throw new XRuntimeException("Try to write final field %s", field.getName());
}
}else{
field.set(null, value);
}
}
private int getPrimitiveID(XVirtualMachine vm){
XClass xClass = fieldType.getXClass(vm);
if(xClass==null)
return XPrimitive.OBJECT;
return XPrimitive.getPrimitiveID(xClass);
}
private void resolve(XVirtualMachine vm, XMethodExecutor methodExecutor){
if(field==null){
XClass xClass = vm.getClassProvider().getXClass(className);
field = xClass.getField(fieldName);
XChecks.checkAccess(methodExecutor.getMethod().getDeclaringClass(), field);
if(!field.getType().equals(fieldType)){
throw new XRuntimeException("Type of field %s has changed", field);
}
if(!XModifier.isStatic(field.getModifier())){
throw new XRuntimeException("Field %s isn't static", field);
}
}
}
@Override
protected void save(XOutputStream outputStream) throws IOException {
outputStream.writeUTF(className);
outputStream.writeUTF(fieldName);
fieldType.save(outputStream);
}
@Override
public String getSource() {
return "ssf "+className+"."+fieldName+":"+fieldType;
}
}