Skip to content
Snippets Groups Projects
Select Git revision
  • 2f086c36f1c5c9b92b4ad793b23002d0f78647fe
  • master default protected
2 results

Instruction.java

Blame
  • Forked from Toby Murray / swen90006-a2-2020
    Source project has a limited visibility.
    Instruction.java 6.52 KiB
    // import java.util.Arrays;
    // import java.util.ArrayList;
    
    import java.lang.reflect.Array;
    import java.util.*;
    import java.util.stream.Collectors;
    
    public enum Instruction {
        PLUS("+",new OperandType[]{}, 2, -1, 2),
        SUB("-",new OperandType[]{}, 2, -1, 2),
        MULT("*",new OperandType[]{}, 2, -1, 2),
        DIV("/",new OperandType[]{}, 2, -1, 2),
        PUSH("push",new OperandType[]{OperandType.STRING}, 0, 1, 3),
        POP("pop",new OperandType[]{}, 1, -1, 4),
        LOAD("load",new OperandType[]{OperandType.STRING}, 0, 1, 1), //Note. Check variable existence
        REM("remove",new OperandType[]{OperandType.STRING}, 0, 0, 1), //Note. Check variable existence
        STORE("store",new OperandType[]{OperandType.STRING}, 1, -1, 1),
        SAVE("save",new OperandType[]{OperandType.STRING}, 0, 0, 1),
        LIST("list",new OperandType[]{}, 0, 0, 1),
        PRINT("print",new OperandType[]{}, 0, 0, 1);
    
        public static String getBNF(){
            String grammar = "<INSTRUCTION> ::= \n";
            Instruction[] INSTS = Instruction.values();
            boolean firstInst = true;
            for (Instruction inst : INSTS){
                if (firstInst){
                    grammar += "      \"";
                    firstInst = false;
                }else{
                    grammar += "    | \"";
                }
                grammar += inst.getOpcode() + "\"";
                for (OperandType op : inst.getOperands()){
                    grammar += " <" + op.toString() + ">";
                }
                grammar += "\n";
            }
            return grammar;
        }
        
        static Integer maxProbability = 0;
    
        private final String opcode;
        private final OperandType[] operands;
        private final Integer minItemsInStack;
        private final Integer changeToStack;
        private final Integer probability;
    
        Instruction(String opcode, OperandType[] operands, Integer minItemsInStack, Integer changeToStack, Integer probability){
            this.opcode = opcode;
            this.operands = operands;
            this.minItemsInStack = minItemsInStack;
            this.changeToStack = changeToStack;
            this.probability = probability;
        }
    
        // List of all instructions
        private static final ArrayList<Instruction> ALL_INSTRUCTIONS = new ArrayList<>(Arrays.asList(values()));
        // private static final int ALL_LENGTH = ALL_INSTRUCTIONS.size();
        private static final ArrayList<Integer> ALL_CUML_PROB = new ArrayList<Integer>();
        private static int ALL_MAX_CUML_PROB = 0;
    
        // List of instructions with zero min stack
        private static final ArrayList<Instruction> MAX_ZERO_INSTRUCTIONS = new ArrayList<>(
                ALL_INSTRUCTIONS.stream().filter(i -> i.minItemsInStack == 0).collect(Collectors.toList()));
        // private static final int ZERO_LENGTH = MAX_ZERO_INSTRUCTIONS.size();
        private static final ArrayList<Integer> ZERO_CUML_PROB = new ArrayList<Integer>();
        private static Integer ZERO_MAX_CUML_PROB = 0;
    
        // List of instructions with one or less min stack
        private static final ArrayList<Instruction> MAX_ONE_INSTRUCTIONS = new ArrayList<>(
                ALL_INSTRUCTIONS.stream().filter(i -> i.minItemsInStack <= 1).collect(Collectors.toList()));
        // private static final int ONE_LENGTH = MAX_ONE_INSTRUCTIONS.size();
        private static final ArrayList<Integer> ONE_CUML_PROB = new ArrayList<Integer>();
        private static Integer ONE_MAX_CUML_PROB = 0;
    
        // Random generator
        private static Random rand = new Random(System.currentTimeMillis());
    
    
    
        // Returns a random instruction based on the stack size to prevent repeated
        // requests
        public static Instruction getRandomInstruction(int max, int[] addProb) {
            // Check if cumlative probabilities have been calculated
            checkProbability(addProb);
    
            ArrayList<Instruction> instructions;
            ArrayList<Integer> instCumlProbs;
            int value;
            if (max == 0) {
                // Select random from instructions with 0 min stack
                instructions = MAX_ZERO_INSTRUCTIONS;
                instCumlProbs = ZERO_CUML_PROB;
                value = rand.nextInt(ZERO_MAX_CUML_PROB);
            } else if (max == 1) {
                // Select random from instructions with 1 or less min stack
                instructions = MAX_ONE_INSTRUCTIONS;
                instCumlProbs = ONE_CUML_PROB;
                value = rand.nextInt(ONE_MAX_CUML_PROB);
            } else {
                // Select random from all
                instructions = ALL_INSTRUCTIONS;
                instCumlProbs = ALL_CUML_PROB;
                value = rand.nextInt(ALL_MAX_CUML_PROB);
            }
    
            // Determine instruction to return using appropriate cumlative probability array
            int i = 0;
            for (Integer cumlativeProb : instCumlProbs) {
                if (value < cumlativeProb) {
                    return instructions.get(i);
                }
                i++;
            }
            return instructions.get(instructions.size() - 1);
    
        }
    
        // Called before doing probability calculations to check if the clumulative
        // probabilities have been calculated
        private static void checkProbability(int[] addProb) {
            // Check if cumlative probabilities have been calculated. If not, do so.
            if (Instruction.ALL_MAX_CUML_PROB == 0) {
                Integer cumProb = 0;
                for (Instruction instruction : ALL_INSTRUCTIONS) {
                    cumProb += instruction.probability + addProb[instruction.ordinal()];
                    ALL_CUML_PROB.add(cumProb);
                }
                ALL_MAX_CUML_PROB = cumProb;
    
                cumProb = 0;
                for (Instruction instruction : MAX_ZERO_INSTRUCTIONS) {
                    cumProb += instruction.probability + addProb[instruction.ordinal()];
                    ZERO_CUML_PROB.add(cumProb);
                }
                ZERO_MAX_CUML_PROB = cumProb;
    
                cumProb = 0;
                for (Instruction instruction : MAX_ONE_INSTRUCTIONS) {
                    cumProb += instruction.probability + addProb[instruction.ordinal()];
                    ONE_CUML_PROB.add(cumProb);
                }
                ONE_MAX_CUML_PROB = cumProb;
            }
        }
    
        public String getOpcode(){
            return opcode;
        }
        
        public OperandType[] getOperands(){
            return operands;
        }
    
        public boolean isValid(Integer stackSize) {
            return this.minItemsInStack >= stackSize;
        }
    
        public Integer getStackChange() {
            return this.changeToStack;
        }
        
        public String toString(){
            String operandsString = "";
            for (OperandType op : operands) {
                operandsString += " " + op.toString();
            }
            return "\"" + opcode + "\"" + operandsString;
        }
    
        public Integer getProbability() {
            return this.probability;
        }
    }