/****************************************************************************** * Name: Reference Solution * NetID: refsoln * Precept: P00 * * Description: Renumbers TOY programs. ******************************************************************************/ public class ToyStory { // a symbol table whose keys are memory locations and whose values are instructions private ST code = new ST(); // adds each line to the ST, where a line is a String in the format: "XX: XXXX" public ToyStory(String[] lines) { for (String line : lines) code.put(line.substring(0, 2), line.substring(4)); } // return a String containing the program, in the form: "XX: XXXX\nXX: XXXX\n" public String toString() { StringBuilder result = new StringBuilder(); for (String line : code.keys()) result.append(line + ": " + code.get(line) + "\n"); return result.toString(); } // returns true if there is an instruction defined at memory location 'mem' public boolean isDefined(String mem) { return code.contains(mem); } // returns true if instruction at 'mem' has op code C or D and ends in 'addr' // assumes that there is an instruction defined at 'mem' public boolean containsJumpTo(String mem, String addr) { String instruction = code.get(mem); char opCode = instruction.charAt(0); return (opCode == 'C' || opCode == 'D') && instruction.substring(2).equals(addr); } // FOR FULL CREDIT, MUST CORRECTLY USE containsJumpTo() AND increment() (SEE BELOW) // finds all instructions that jump to 'addr' and changes them to jump to 'addr'+1 public void incrementAllJumpsTo(String addr) { for (String mem : code.keys()) if (containsJumpTo(mem, addr)) code.put(mem, code.get(mem).substring(0, 2) + increment(code.get(mem).substring(2))); } // DO NOT EDIT THIS METHOD // IT IS PROVIDED TO MAKE INCREMENTING EASIER IN THE METHOD ABOVE // takes a 2-hex-digit number as input, gives the next 2-digit-hex number as output // for example, increment("19") returns "1A" public static String increment(String addr) { return String.format("%02X", Integer.parseInt(addr, 16) + 1); } // EXTRA CREDIT // FOR ONE POINT, IMPLEMENT A WORKING NON-RECURSIVE SOLUTION // FOR TWO POINTS, IMPLEMENT A WORKING RECURSIVE SOLUTION // move all consecutive instructions at and after memory address 'min' down // to the following memory address. also, maintains connections between all // jumps and the instructions they jump to by calling incrementAllJumpsTo() public void renumberAfter(String min) { if (isDefined(increment(min))) renumberAfter(increment(min)); code.put(increment(min), code.get(min)); incrementAllJumpsTo(min); code.remove(min); } // DO NOT EDIT THIS METHOD // IT IS PROVIDED TO HELP YOU TEST YOUR EXTRA CREDIT SOLUTION // associates 'mem' with 'instruction' and updates the existing code accordingly public void addLine(String mem, String instruction) { // before we add this line, let's push everything down if (isDefined(mem)) renumberAfter(mem); // then add this line code.put(mem, instruction); } // YOU MAY EDIT THIS METHOD BUT CODE WRITTEN HERE WILL NOT BE GRADED public static void main(String[] args) { // THIS IS JUST A DUMMY TOY PROGRAM TO TEST YOUR CODE String[] toy = {"10: 1000", "11: C010"}; // READ IT IN, PRINT IT OUT ToyStory story = new ToyStory(toy); StdOut.println(story.toString()); // ARE THERE INSTRUCTIONS DEFINED AT THESE MEMORY LOCATIONS? StdOut.println(story.isDefined("10")); // TRUE StdOut.println(story.isDefined("12")); // FALSE // DO THE FOLLOWING LINES CONTAIN JUMPS TO THESE ADDRESSES? StdOut.println(story.containsJumpTo("11", "10")); // TRUE StdOut.println(story.containsJumpTo("11", "11")); // FALSE // LET'S CHANGE ALL JUMPS TO 10 TO JUMP TO 11 INSTEAD story.incrementAllJumpsTo("10"); StdOut.println(story); // RESULT: "10: 1000\n11: C011\n" } }