// Path: src/main/java/com/aaront/exercise/jvm/ClassFile.java
// @Data
// public class ClassFile {
//     private String magicNumber;
//     private int majorVersion;
//     private int minorVersion;
//     private ClassIndex classIndex;
//     private InterfaceIndex interfaceIndex;
//     private ConstantPool constantPool;
//     private List<ClassAccessFlag> accessFlags;
//     private List<Field> fields;
//     private Map<Pair<String, String>, Method> methods;
// 
//     public String getSuperClassName(){
//         ClassConstant superClass = (ClassConstant)this.getConstantPool().getConstantInfo(this.classIndex.getSuperClassIndex());
//         return superClass.getClassName();
//     }
// 
//     public Method getMethod(String methodName, String paramAndReturnType){
// 
//         for(Method m :methods.values()){
// 
//             int nameIndex = m.getNameIndex();
//             int descriptionIndex = m.getDescriptorIndex();
// 
//             String name = this.getConstantPool().getUTF8String(nameIndex);
//             String desc = this.getConstantPool().getUTF8String(descriptionIndex);
//             if(name.equals(methodName) && desc.equals(paramAndReturnType)){
//                 return m;
//             }
//         }
//         return null;
//     }
// }
// 
// Path: src/main/java/com/aaront/exercise/jvm/constant/ConstantPool.java
// @Data
// public class ConstantPool {
//     private List<AbstractConstant> abstractConstant = new ArrayList<>();
// 
//     public ConstantPool(List<AbstractConstant> abstractConstant) {
//         this.abstractConstant = abstractConstant;
//     }
// 
//     public ConstantPool() {
// 
//     }
// 
//     public AbstractConstant getConstantInfo(int index) {
//         return this.abstractConstant.get(index);
//     }
// 
//     public String getUTF8String(int index) {
//         return ((UTF8Constant) this.abstractConstant.get(index)).getValue();
//     }
// 
//     public int getSize() {
//         return this.abstractConstant.size() - 1;
//     }
// }
// 
// Path: src/main/java/com/aaront/exercise/jvm/engine/ExecutionResult.java
// @Data
// public class ExecutionResult {
// 
//     private NextAction nextAction = RUN_NEXT_CMD;
// 
//     private int nextCmdOffset = 0;
// 
//     private Method nextMethod;
// 
//     public boolean isPauseAndRunNewFrame() {
//         return this.nextAction == PAUSE_AND_RUN_NEW_FRAME;
//     }
// 
//     public boolean isExitCurrentFrame() {
//         return this.nextAction == EXIT_CURRENT_FRAME;
//     }
// 
//     public boolean isRunNextCmd() {
//         return this.nextAction == RUN_NEXT_CMD;
//     }
// 
//     public boolean isJump() {
//         return this.nextAction == JUMP;
//     }
// }
// 
// Path: src/main/java/com/aaront/exercise/jvm/engine/JavaObject.java
// @Data
// public class JavaObject {
//     private JavaType type;
//     private String className;
// 
//     private Map<String, JavaObject> fieldValues = new HashMap<>();
// 
//     private String stringValue;
// 
//     private int intValue;
// 
//     private float floatValue;
// 
//     private long longValue;
// 
//     public void setFieldValue(String fieldName, JavaObject fieldValue) {
//         fieldValues.put(fieldName, fieldValue);
//     }
// 
//     public JavaObject(JavaType type) {
//         this.type = type;
//     }
// 
//     public JavaObject getFieldValue(String fieldName) {
//         return this.fieldValues.get(fieldName);
//     }
// 
//     public String toString() {
//         switch (this.getType()) {
//             case INT:
//                 return String.valueOf(this.intValue);
//             case STRING:
//                 return this.stringValue;
//             case OBJECT:
//                 return this.className + ":" + this.fieldValues;
//             case FLOAT:
//                 return String.valueOf(this.floatValue);
//             case LONG:
//                 return String.valueOf(this.longValue);
//             default:
//                 return null;
//         }
//     }
// }
// 
// Path: src/main/java/com/aaront/exercise/jvm/engine/StackFrame.java
// @Data
// public class StackFrame {
//     // 下一条指令的位置(偏移量)
//     private int index = 0;
//     private JavaObject returnValue = null;
//     private StackFrame callerStackFrame;
//     private ConstantPool pool;
//     private Stack<JavaObject> operandStack;
//     //这里最好是用数据来保存, 如果使用List会很不方便, 因为一些指令会对localVariableTable指定位置设置值, 如果使用List且List的size<所要设置的位置会报错
//     private JavaObject[] localVariableTable;
//     private Method method;
//     private List<AbstractCommand> commands;
// 
//     public StackFrame(Method method) {
//         this.method = method;
//         this.commands = method.getCodeAttribute().getCommands();
//         this.pool = method.getPool();
//         this.operandStack = new Stack<>();
//         this.localVariableTable = new JavaObject[method.getCodeAttribute().getMaxLocals()];
//     }
// }


import com.aaront.exercise.jvm.ClassFile;
import com.aaront.exercise.jvm.constant.ConstantPool;
import com.aaront.exercise.jvm.engine.ExecutionResult;
import com.aaront.exercise.jvm.engine.JavaObject;
import com.aaront.exercise.jvm.engine.StackFrame;
import java.util.Stack;
package com.aaront.exercise.jvm.commands;



/**
 * @author tonyhui
 * @since 17/6/17
 */
public class DupCommand extends NoOperandCommand {
    public DupCommand(ClassFile clzFile, String opCode) {
// Path: src/main/java/com/aaront/exercise/jvm/ClassFile.java
// @Data
// public class ClassFile {
//     private String magicNumber;
//     private int majorVersion;
//     private int minorVersion;
//     private ClassIndex classIndex;
//     private InterfaceIndex interfaceIndex;
//     private ConstantPool constantPool;
//     private List<ClassAccessFlag> accessFlags;
//     private List<Field> fields;
//     private Map<Pair<String, String>, Method> methods;
// 
//     public String getSuperClassName(){
//         ClassConstant superClass = (ClassConstant)this.getConstantPool().getConstantInfo(this.classIndex.getSuperClassIndex());
//         return superClass.getClassName();
//     }
// 
//     public Method getMethod(String methodName, String paramAndReturnType){
// 
//         for(Method m :methods.values()){
// 
//             int nameIndex = m.getNameIndex();
//             int descriptionIndex = m.getDescriptorIndex();
// 
//             String name = this.getConstantPool().getUTF8String(nameIndex);
//             String desc = this.getConstantPool().getUTF8String(descriptionIndex);
//             if(name.equals(methodName) && desc.equals(paramAndReturnType)){
//                 return m;
//             }
//         }
//         return null;
//     }
// }
// 
// Path: src/main/java/com/aaront/exercise/jvm/constant/ConstantPool.java
// @Data
// public class ConstantPool {
//     private List<AbstractConstant> abstractConstant = new ArrayList<>();
// 
//     public ConstantPool(List<AbstractConstant> abstractConstant) {
//         this.abstractConstant = abstractConstant;
//     }
// 
//     public ConstantPool() {
// 
//     }
// 
//     public AbstractConstant getConstantInfo(int index) {
//         return this.abstractConstant.get(index);
//     }
// 
//     public String getUTF8String(int index) {
//         return ((UTF8Constant) this.abstractConstant.get(index)).getValue();
//     }
// 
//     public int getSize() {
//         return this.abstractConstant.size() - 1;
//     }
// }
// 
// Path: src/main/java/com/aaront/exercise/jvm/engine/ExecutionResult.java
// @Data
// public class ExecutionResult {
// 
//     private NextAction nextAction = RUN_NEXT_CMD;
// 
//     private int nextCmdOffset = 0;
// 
//     private Method nextMethod;
// 
//     public boolean isPauseAndRunNewFrame() {
//         return this.nextAction == PAUSE_AND_RUN_NEW_FRAME;
//     }
// 
//     public boolean isExitCurrentFrame() {
//         return this.nextAction == EXIT_CURRENT_FRAME;
//     }
// 
//     public boolean isRunNextCmd() {
//         return this.nextAction == RUN_NEXT_CMD;
//     }
// 
//     public boolean isJump() {
//         return this.nextAction == JUMP;
//     }
// }
// 
// Path: src/main/java/com/aaront/exercise/jvm/engine/JavaObject.java
// @Data
// public class JavaObject {
//     private JavaType type;
//     private String className;
// 
//     private Map<String, JavaObject> fieldValues = new HashMap<>();
// 
//     private String stringValue;
// 
//     private int intValue;
// 
//     private float floatValue;
// 
//     private long longValue;
// 
//     public void setFieldValue(String fieldName, JavaObject fieldValue) {
//         fieldValues.put(fieldName, fieldValue);
//     }
// 
//     public JavaObject(JavaType type) {
//         this.type = type;
//     }
// 
//     public JavaObject getFieldValue(String fieldName) {
//         return this.fieldValues.get(fieldName);
//     }
// 
//     public String toString() {
//         switch (this.getType()) {
//             case INT:
//                 return String.valueOf(this.intValue);
//             case STRING:
//                 return this.stringValue;
//             case OBJECT:
//                 return this.className + ":" + this.fieldValues;
//             case FLOAT:
//                 return String.valueOf(this.floatValue);
//             case LONG:
//                 return String.valueOf(this.longValue);
//             default:
//                 return null;
//         }
//     }
// }
// 
// Path: src/main/java/com/aaront/exercise/jvm/engine/StackFrame.java
// @Data
// public class StackFrame {
//     // 下一条指令的位置(偏移量)
//     private int index = 0;
//     private JavaObject returnValue = null;
//     private StackFrame callerStackFrame;
//     private ConstantPool pool;
//     private Stack<JavaObject> operandStack;
//     //这里最好是用数据来保存, 如果使用List会很不方便, 因为一些指令会对localVariableTable指定位置设置值, 如果使用List且List的size<所要设置的位置会报错
//     private JavaObject[] localVariableTable;
//     private Method method;
//     private List<AbstractCommand> commands;
// 
//     public StackFrame(Method method) {
//         this.method = method;
//         this.commands = method.getCodeAttribute().getCommands();
//         this.pool = method.getPool();
//         this.operandStack = new Stack<>();
//         this.localVariableTable = new JavaObject[method.getCodeAttribute().getMaxLocals()];
//     }
// }


// Path: src/main/java/com/aaront/exercise/jvm/commands/DupCommand.java
import com.aaront.exercise.jvm.ClassFile;
import com.aaront.exercise.jvm.constant.ConstantPool;
import com.aaront.exercise.jvm.engine.ExecutionResult;
import com.aaront.exercise.jvm.engine.JavaObject;
import com.aaront.exercise.jvm.engine.StackFrame;
import java.util.Stack;

package com.aaront.exercise.jvm.commands;



/**
 * @author tonyhui
 * @since 17/6/17
 */
public class DupCommand extends NoOperandCommand {
    public DupCommand(ClassFile clzFile, String opCode) {
        super(clzFile, opCode);