vm to hack translator - part 1.
My code is not complete yet.
It does not support multiple files or directories. That is something I will do later.
I will first test with SimpleAdd.tst.
Pre conditions are as follows:
set RAM[0] 256
And the test itself is:
push constant 7 push constant 8 add
And the expected results are as follows:
| RAM[0] | RAM[256] | | 257 | 15 |
So this is the output of my translator:
// Push Constant @7 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @8 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // add @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = D + M @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End add
And now I will run this translated code in CPU Simulator and make the verification myself. However I will add the the following piece of code at the very beginning to satisfy preconditions:
@256 D = A @R0 M = D
Ok let 's run the code and see what happens:
Seems ok!!!
Lets move on to the next test: StackTest.
Pre conditions are as follows:
set RAM[0] 256
And the test itself:
push constant 17 push constant 17 eq push constant 17 push constant 16 eq push constant 16 push constant 17 eq push constant 892 push constant 891 lt push constant 891 push constant 892 lt push constant 891 push constant 891 lt push constant 32767 push constant 32766 gt push constant 32766 push constant 32767 gt push constant 32766 push constant 32766 gt push constant 57 push constant 31 push constant 53 add push constant 112 sub neg and push constant 82 or not
And the expected results are as follows:
| RAM[0] | RAM[256] | RAM[257] | RAM[258] | RAM[259] | RAM[260] | | 266 | -1 | 0 | 0 | 0 | -1 | | RAM[261] | RAM[262] | RAM[263] | RAM[264] | RAM[265] | | 0 | -1 | 0 | 0 | -91 |
So this is the output of my translator:
// Push Constant @17 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @17 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // equals @R0 M = M - 1 @R0 A = M D = M @equalstrue.1 D;JEQ @equalsfalse.1 D;JNE (equalstrue.1) @1 A = - A D = A @0 A = M M = D @equalsend.1 0;JMP (equalsfalse.1) @0 D = A @0 A = M M = D @equalsend.1 0;JMP (equalsend.1) @R0 M = M + 1 // end equals // Push Constant @17 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @16 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // equals @R0 M = M - 1 @R0 A = M D = M @equalstrue.2 D;JEQ @equalsfalse.2 D;JNE (equalstrue.2) @1 A = - A D = A @0 A = M M = D @equalsend.2 0;JMP (equalsfalse.2) @0 D = A @0 A = M M = D @equalsend.2 0;JMP (equalsend.2) @R0 M = M + 1 // end equals // Push Constant @16 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @17 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // equals @R0 M = M - 1 @R0 A = M D = M @equalstrue.3 D;JEQ @equalsfalse.3 D;JNE (equalstrue.3) @1 A = - A D = A @0 A = M M = D @equalsend.3 0;JMP (equalsfalse.3) @0 D = A @0 A = M M = D @equalsend.3 0;JMP (equalsend.3) @R0 M = M + 1 // end equals // Push Constant @892 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @891 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // less than @R0 M = M - 1 @R0 A = M D = M @lesstrue.1 D;JLT @lessfalse.1 D;JGE (lesstrue.1) @1 A = - A D = A @0 A = M M = D @lessend.1 0;JMP (lessfalse.1) @0 D = A @0 A = M M = D @lessend.1 0;JMP (lessend.1) @R0 M = M + 1 // less than // Push Constant @891 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @892 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // less than @R0 M = M - 1 @R0 A = M D = M @lesstrue.2 D;JLT @lessfalse.2 D;JGE (lesstrue.2) @1 A = - A D = A @0 A = M M = D @lessend.2 0;JMP (lessfalse.2) @0 D = A @0 A = M M = D @lessend.2 0;JMP (lessend.2) @R0 M = M + 1 // less than // Push Constant @891 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @891 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // less than @R0 M = M - 1 @R0 A = M D = M @lesstrue.3 D;JLT @lessfalse.3 D;JGE (lesstrue.3) @1 A = - A D = A @0 A = M M = D @lessend.3 0;JMP (lessfalse.3) @0 D = A @0 A = M M = D @lessend.3 0;JMP (lessend.3) @R0 M = M + 1 // less than // Push Constant @32767 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @32766 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // greater than @R0 M = M - 1 @R0 A = M D = M @greatertrue.1 D;JGT @greaterfalse.1 D;JLE (greatertrue.1) @1 A = - A D = A @0 A = M M = D @greatersend.1 0;JMP (greaterfalse.1) @0 D = A @0 A = M M = D @greatersend.1 0;JMP (greatersend.1) @R0 M = M + 1 // greater than // Push Constant @32766 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @32767 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // greater than @R0 M = M - 1 @R0 A = M D = M @greatertrue.2 D;JGT @greaterfalse.2 D;JLE (greatertrue.2) @1 A = - A D = A @0 A = M M = D @greatersend.2 0;JMP (greaterfalse.2) @0 D = A @0 A = M M = D @greatersend.2 0;JMP (greatersend.2) @R0 M = M + 1 // greater than // Push Constant @32766 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @32766 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // greater than @R0 M = M - 1 @R0 A = M D = M @greatertrue.3 D;JGT @greaterfalse.3 D;JLE (greatertrue.3) @1 A = - A D = A @0 A = M M = D @greatersend.3 0;JMP (greaterfalse.3) @0 D = A @0 A = M M = D @greatersend.3 0;JMP (greatersend.3) @R0 M = M + 1 // greater than // Push Constant @57 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @31 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // Push Constant @53 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // add @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = D + M @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End add // Push Constant @112 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // sub @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = M - D @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End sub // neg @R0 M = M - 1 @R0 A = M M = -M @R0 M = M + 1 // end neg // and @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = D & M @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End and // Push Constant @82 D = A @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End Push Constant // or @R0 M = M - 1 @R0 A = M D = M @R0 M = M - 1 @R0 A = M D = D | M @R0 A = M M = D @R0 D = M D = D + 1 @R0 M = D @0 D = A // End or // not @R0 M = M - 1 @R0 A = M M = !M @R0 M = M + 1 // end not
And now I will run this translated code in CPU Simulator and make the verification myself. However I will add the the following piece of code at the very beginning to satisfy preconditions:
@256 D = A @R0 M = D
Ok let 's run the code and see what happens:
Seems like we passed this one as well..
Let 's move on to BasicTest.
Pre conditions:
set RAM[0] 256, set RAM[1] 300, set RAM[2] 400, set RAM[3] 3000, set RAM[4] 3010,
I will set these manually in CPU Simulator before running my translated code.
And the test itself:
push constant 10 pop local 0 push constant 21 push constant 22 pop argument 2 pop argument 1 push constant 36 pop this 6 push constant 42 push constant 45 pop that 5 pop that 2 push constant 510 pop temp 6 push local 0 push that 5 add push argument 1 sub push this 6 push this 6 add sub push temp 6 add
And the expected results:
|RAM[256]|RAM[300]|RAM[401]|RAM[402]|RAM[3006|RAM[3012|RAM[3015|RAM[11] | | 472 | 10 | 21 | 22 | 36 | 42 | 45 | 510 |
Ok I am too lazy to paste the translated code but I can assure you, the code passes..
Lets move on to Pointer Test.. Pass..
Lets move on to Static Test... Pass!!
So here is the first iteration of my code, which already passes all the tests above!
package biz.tugay.vmtranslator; /** * User: koray@tugay.biz on 16/04/16 at 10:43. */ public class VMTranslator { public static String translateVMLine(String vmLine, String fileName) { String translatedLine; if (vmLine.startsWith("push")) { translatedLine = translatePush(vmLine, fileName); } else if (vmLine.startsWith("pop")) { translatedLine = translatePop(vmLine, fileName); } else { translatedLine = ArithmeticTranslator.translateArithmetic(vmLine); } return "\n" + translatedLine + "\n"; } private static String translatePush(String vmLine, String fileName) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); if (vmLine.startsWith("constant")) { return PushTranslator.translatePushConstant(vmLine); } if (vmLine.startsWith("local")) { return PushTranslator.translatePushLocal(vmLine); } if (vmLine.startsWith("argument")) { return PushTranslator.translatePushArgument(vmLine); } if (vmLine.startsWith("this")) { return PushTranslator.translatePushThis(vmLine); } if (vmLine.startsWith("local")) { return PushTranslator.translatePushThat(vmLine); } if (vmLine.startsWith("temp")) { return PushTranslator.translatePushTemp(vmLine); } if (vmLine.startsWith("that")) { return PushTranslator.translatePushThat(vmLine); } if (vmLine.startsWith("pointer")) { return PushTranslator.translatePushPointer(vmLine); } if (vmLine.startsWith("static")) { return PushTranslator.translatePushStatic(vmLine, fileName); } return null; } private static String translatePop(String vmLine, String fileName) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); if (vmLine.startsWith("local")) { return PopTranslator.translatePopLocal(vmLine); } if (vmLine.startsWith("argument")) { return PopTranslator.translatePopArgument(vmLine); } if (vmLine.startsWith("this")) { return PopTranslator.translatePopThis(vmLine); } if (vmLine.startsWith("that")) { return PopTranslator.translatePopThat(vmLine); } if (vmLine.startsWith("temp")) { return PopTranslator.translatePopTemp(vmLine); } if (vmLine.startsWith("pointer")) { return PopTranslator.translatePopPointer(vmLine); } if (vmLine.startsWith("static")) { return PopTranslator.translatePopStatic(vmLine, fileName); } return null; } } package biz.tugay.vmtranslator; /** * User: koray@tugay.biz on 16/04/16 at 20:37. */ public class PushTranslator { public static String translatePushConstant(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "// Push Constant\n" + "@" + vmLine + "\n" + "D = A\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n" + "// End Push Constant\n"; } public static String translatePushLocal(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@" + vmLine + "\n" + "D = A\n" + "@LCL\n" + "D = D + M\n" + "A = D\n" + "D = M\n" + "\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n"; } public static String translatePushArgument(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@" + vmLine + "\n" + "D = A\n" + "@ARG\n" + "D = D + M\n" + "\n" + "A = D\n" + "D = M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n"; } public static String translatePushThis(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@" + vmLine + "\n" + "D = A\n" + "@THIS\n" + "D = D + M\n" + "\n" + "A = D\n" + "D = M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n"; } public static String translatePushThat(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@" + vmLine + "\n" + "D = A\n" + "@THAT\n" + "D = D + M\n" + "\n" + "A = D\n" + "D = M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n"; } public static String translatePushTemp(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); int index = 5 + Integer.valueOf(vmLine); return "@R" + index + "\n" + "D = M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "M = M + 1\n"; } public static String translatePushPointer(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); if (vmLine.equals("0")) { return "@THIS\n" + "D = M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "M = M + 1\n"; } if (vmLine.equals("1")) { return "@THAT\n" + "D = M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "M = M + 1\n"; } return null; } public static String translatePushStatic(String vmLine, String fileName) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@" + fileName + "." + vmLine + "\n" + "D = M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "M = M + 1\n"; } } package biz.tugay.vmtranslator; /** * User: koray@tugay.biz on 16/04/16 at 20:38. */ public class PopTranslator { public static String translatePopLocal(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@LCL\n" + "D = M\n" + "@" + vmLine + "\n" + "D = D + A\n" + "@LCL\n" + "M = D\n" + "\n" + "@R0\n" + "M = M - 1\n" + "A = M\n" + "D = M\n" + "\n" + "@LCL\n" + "A = M\n" + "M = D\n" + "@LCL\n" + "D = M\n" + "@" + vmLine + "\n" + "D = D - A\n" + "@LCL\n" + "M = D\n"; } public static String translatePopArgument(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@ARG\n" + "D = M\n" + "@" + vmLine + "\n" + "D = D + A\n" + "@ARG\n" + "M = D\n" + "\n" + "@R0\n" + "M = M - 1\n" + "A = M\n" + "D = M\n" + "\n" + "@ARG\n" + "A = M\n" + "M = D\n" + "@ARG\n" + "D = M\n" + "@" + vmLine + "\n" + "D = D - A\n" + "@ARG\n" + "M = D\n"; } public static String translatePopThis(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@THIS\n" + "D = M\n" + "@" + vmLine + "\n" + "D = D + A\n" + "@THIS\n" + "M = D\n" + "\n" + "@R0\n" + "M = M - 1\n" + "A = M\n" + "D = M\n" + "\n" + "@THIS\n" + "A = M\n" + "M = D\n" + "@THIS\n" + "D = M\n" + "@" + vmLine + "\n" + "D = D - A\n" + "@THIS\n" + "M = D\n"; } public static String translatePopThat(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@THAT\n" + "D = M\n" + "@" + vmLine + "\n" + "D = D + A\n" + "@THAT\n" + "M = D\n" + "\n" + "@R0\n" + "M = M - 1\n" + "A = M\n" + "D = M\n" + "\n" + "@THAT\n" + "A = M\n" + "M = D\n" + "@THAT\n" + "D = M\n" + "@" + vmLine + "\n" + "D = D - A\n" + "@THAT\n" + "M = D\n"; } public static String translatePopTemp(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); int index = 5 + Integer.valueOf(vmLine); return "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "@R" + index + "\n" + "M = D\n"; } public static String translatePopPointer(String vmLine) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); if (vmLine.equals("0")) { return "@R0\n" + "M = M - 1\n" + "A = M\n" + "D = M\n" + "\n" + "@THIS\n" + "M = D\n"; } if (vmLine.equals("1")) { return "@R0\n" + "M = M - 1\n" + "A = M\n" + "D = M\n" + "\n" + "@THAT\n" + "M = D\n"; } return null; } public static String translatePopStatic(String vmLine, String fileName) { vmLine = vmLine.substring(vmLine.indexOf(' ') + 1, vmLine.length()); return "@R0\n" + "M = M -1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "@" + fileName + "." + vmLine + "\n" + "M = D"; } } package biz.tugay.vmtranslator; /** * User: koray@tugay.biz on 16/04/16 at 20:38. */ public class ArithmeticTranslator { public static String translateArithmetic(String vmLine) { if (vmLine.startsWith("add")) { return translateAdd(); } if (vmLine.startsWith("sub")) { return translateSub(); } if (vmLine.startsWith("eq")) { return translateEq(); } if (vmLine.startsWith("gt")) { return translateGt(); } if (vmLine.startsWith("lt")) { return translateLt(); } if (vmLine.startsWith("and")) { return translateAnd(); } if (vmLine.startsWith("or")) { return translateOr(); } if (vmLine.startsWith("neg")) { return translateNeg(); } if (vmLine.startsWith("not")) { return translateNot(); } return ""; } private static String translateAdd() { return "// add\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = D + M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n" + "// End add\n"; } private static String translateSub() { return "// sub\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M - D\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n" + "// End sub\n"; } private static String translateNot() { return "// not\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "M = !M\n" + "@R0\n" + "M = M + 1\n" + "// end not"; } private static String translateNeg() { return "// neg\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "M = -M\n" + "@R0\n" + "M = M + 1\n" + "// end neg"; } private static String translateOr() { return "// or\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = D | M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n" + "// End or\n"; } private static String translateAnd() { return "// and\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = D & M\n" + "@R0\n" + "A = M\n" + "M = D\n" + "@R0\n" + "D = M\n" + "D = D + 1\n" + "@R0\n" + "M = D\n" + "@0\n" + "D = A\n" + "// End and\n"; } private static int ltCounter = 1; private static String translateLt() { String sub = translateSub(); sub = sub + "// less than \n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "\n" + "@lesstrue." + ltCounter + "\n" + "D;JLT\n" + "\n" + "@lessfalse." + ltCounter + "\n" + "D;JGE\n" + "\n" + "(lesstrue." + ltCounter + ")\n" + "@1\n" + "A = - A\n" + "D = A\n" + "@0\n" + "A = M\n" + "M = D\n" + "@lessend." + ltCounter + "\n" + "0;JMP\n" + "\n" + "(lessfalse." + ltCounter + ")\n" + "@0\n" + "D = A\n" + "@0\n" + "A = M\n" + "M = D\n" + "@lessend." + ltCounter + "\n" + "0;JMP\n" + "\n" + "\n" + "(lessend." + ltCounter + ")\n" + "@R0\n" + "M = M + 1\n" + "// less than"; ltCounter++; return sub; } private static int gtCounter = 1; private static String translateGt() { String sub = translateSub(); sub = sub + "// greater than \n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "\n" + "@greatertrue." + gtCounter + "\n" + "D;JGT\n" + "\n" + "@greaterfalse." + gtCounter + "\n" + "D;JLE\n" + "\n" + "(greatertrue." + gtCounter + ")\n" + "@1\n" + "A = - A\n" + "D = A\n" + "@0\n" + "A = M\n" + "M = D\n" + "@greatersend." + gtCounter + "\n" + "0;JMP\n" + "\n" + "(greaterfalse." + gtCounter + ")\n" + "@0\n" + "D = A\n" + "@0\n" + "A = M\n" + "M = D\n" + "@greatersend." + gtCounter + "\n" + "0;JMP\n" + "\n" + "\n" + "(greatersend." + gtCounter + ")\n" + "@R0\n" + "M = M + 1\n" + "// greater than"; gtCounter++; return sub; } private static int eqCounter = 1; private static String translateEq() { String sub = translateSub(); sub = sub + "// equals \n" + "@R0\n" + "M = M - 1\n" + "@R0\n" + "A = M\n" + "D = M\n" + "\n" + "@equalstrue." + eqCounter + "\n" + "D;JEQ\n" + "\n" + "@equalsfalse." + eqCounter + "\n" + "D;JNE\n" + "\n" + "(equalstrue." + eqCounter + ")\n" + "@1\n" + "A = - A\n" + "D = A\n" + "@0\n" + "A = M\n" + "M = D\n" + "@equalsend." + eqCounter + "\n" + "0;JMP\n" + "\n" + "(equalsfalse." + eqCounter + ")\n" + "@0\n" + "D = A\n" + "@0\n" + "A = M\n" + "M = D\n" + "@equalsend." + eqCounter + "\n" + "0;JMP\n" + "\n" + "\n" + "(equalsend." + eqCounter + ")\n" + "@R0\n" + "M = M + 1\n" + "// end equals"; eqCounter++; return sub; } }
And this is how I feed the file into my program:
package biz.tugay.vmtranslator; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; /** * User: koray@tugay.biz on 16/04/16 at 10:54. */ public class VMTranslatorTest { public static void main(String[] args) throws FileNotFoundException { final String fileName = "koray.vm"; final File file = new File(fileName); final String fName = file.getName().substring(0, file.getName().indexOf('.')); final Scanner scanner = new Scanner(file); while (scanner.hasNextLine()) { final String vmline = scanner.nextLine(); final String hackAssemblyCode = VMTranslator.translateVMLine(vmline, fName); System.out.println(hackAssemblyCode); } } }
It took me a while to get this project done, and it is not absolutely complete I guess.