-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
finish Memory Access - Basic test/week 07
- Loading branch information
1 parent
b3d3660
commit 5bab8c7
Showing
3 changed files
with
368 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
import java.io.*; | ||
|
||
public class CodeWriter { | ||
private static Integer numJump; | ||
private String pathAssembly; | ||
private File assemblyTranslate; | ||
public FileWriter assemblyWriter; | ||
|
||
public CodeWriter(String pathAssembly) throws IOException { | ||
|
||
this.pathAssembly = pathAssembly; | ||
CodeWriter.numJump = 0; | ||
this.assemblyTranslate = new File(pathAssembly.replace(".vm", ".asm")); | ||
System.out.println(pathAssembly.replace(".vm", ".asm")); | ||
try { | ||
this.assemblyWriter = new FileWriter(this.assemblyTranslate); | ||
} catch (FileNotFoundException e) { | ||
System.out.println("File not found!"); | ||
} | ||
} | ||
|
||
public void writeArithmetic(String arg1) throws IOException { | ||
|
||
this.assemblyWriter.write("//" + arg1 + "\n"); | ||
|
||
switch (arg1) { | ||
|
||
case "add": | ||
this.assemblyWriter.write(backSP() + "M=D\n" + backSP() + "M=M+D\n" + advSP()); | ||
break; | ||
|
||
case "sub": | ||
this.assemblyWriter.write(backSP() + "D=M\n" + backSP() + "M=M-D\n" + advSP()); | ||
break; | ||
|
||
case "neg": | ||
this.assemblyWriter.write(backSP() + "M=-M\n" + advSP()); | ||
break; | ||
|
||
case "eq": | ||
this.assemblyWriter.write(compCommands("eq")); | ||
break; | ||
|
||
case "gt": | ||
this.assemblyWriter.write(compCommands("gt")); | ||
break; | ||
|
||
case "lt": | ||
this.assemblyWriter.write(compCommands("lt")); | ||
break; | ||
|
||
case "and": | ||
this.assemblyWriter.write(backSP() + "D=M\n" + backSP() + "M=M&D\n" + advSP()); | ||
break; | ||
|
||
case "or": | ||
this.assemblyWriter.write(backSP() + "D=M\n" + backSP() + "M=M|D\n" + advSP()); | ||
break; | ||
|
||
case "not": | ||
this.assemblyWriter.write(backSP() + "M=!M\n" + advSP()); | ||
break; | ||
|
||
default: | ||
System.out.println("Error parsing arithmetic command"); | ||
return; | ||
} | ||
|
||
} | ||
|
||
public void writePushPop(int command, String segment, int c_index) throws IOException { | ||
|
||
this.assemblyWriter | ||
.write("//" + Integer.toString(command) + " " + segment + " " + Integer.toString(c_index) + "\n"); | ||
|
||
if (command == 1) { | ||
handlePush(segment, c_index); | ||
} else if (command == 2) { | ||
handlePop(segment, c_index); | ||
} | ||
} | ||
|
||
public void writeLabel(String segment) throws IOException { | ||
this.assemblyWriter.write("($null" + segment + ")\n"); | ||
} | ||
|
||
public void writeIf(String segment) throws IOException { | ||
this.assemblyWriter.write("@SP\n" + "M=M-1\n" + "A=M\n" + "@null$" + segment + "\n" + "D;JME\n"); | ||
} | ||
|
||
public void writeGo(String segment) throws IOException { | ||
this.assemblyWriter.write("@null$" + segment + "\n" + "0;JMP\n"); | ||
} | ||
|
||
private String chooseSeg(String segment, int c_index) { | ||
String seg = ""; | ||
|
||
switch (segment) { | ||
case ("local"): | ||
seg = "@LCL"; | ||
break; | ||
|
||
case ("argument"): | ||
seg = "@ARG"; | ||
break; | ||
|
||
case ("this"): | ||
seg = "@THIS"; | ||
break; | ||
|
||
case ("that"): | ||
seg = "@THAT"; | ||
break; | ||
|
||
case ("temp"): | ||
seg = "@5"; | ||
return (seg + "\n" + "D=A\n" + "@" + Integer.toString(c_index) + "\n"); | ||
|
||
default: | ||
return ""; | ||
} | ||
return (seg + "\n" + "D=M\n" + "@" + Integer.toString(c_index) + "\n"); | ||
} | ||
|
||
private String compCommands(String type) { | ||
String comparison = "\n"; | ||
|
||
if (type.equals("eq")) { | ||
comparison = "D;JNE\n"; | ||
} else if (type.equals("gt")) { | ||
comparison = "D;JLE\n"; | ||
} else if (type.equals("lt")) { | ||
comparison = "D;JGE\n"; | ||
} | ||
|
||
numJump++; | ||
|
||
return this.backSP() + "D=M\n" + backSP() + "D=M-D\n" + "@FALSE" + numJump + "\n" + comparison + "@SP\n" | ||
+ "A=M\n" + "M=-1\n" + "@CONTINUE" + numJump + "\n" + "D;JMP\n" + "(FALSE" + numJump + ")\n" + "@SP\n" | ||
+ "A=M\n" + "M=0\n" + "(CONTINUE" + numJump + ")\n" + advSP(); | ||
} | ||
|
||
private String staticName(int index) { | ||
String name = this.assemblyTranslate.getName().replace(".asm", ("." + Integer.toString(index))); | ||
return "@" + name + "\n"; | ||
} | ||
|
||
private String backSP() { | ||
return "@SP\n" + "AM=M-1\n"; | ||
} | ||
|
||
private String advSP() { | ||
return "@SP\n" + "M=M+1\n"; | ||
} | ||
|
||
private void handlePush(String segment, int c_index) throws IOException { | ||
// push constant | ||
if (segment.equals("constant")) { | ||
this.assemblyWriter | ||
.write("@" + Integer.toString(c_index) + "\n" + "D=A\n" + "@SP\n" + "A=M\n" + "M=D\n" + advSP()); | ||
|
||
// push local, static, this, that | ||
} else if (!chooseSeg(segment, c_index).isBlank()) { | ||
this.assemblyWriter | ||
.write(chooseSeg(segment, c_index) + "A=A+D\n" + "D=M\n" + "@SP\n" + "A=M\n" + "M=D\n" + advSP()); | ||
|
||
// push temp | ||
} else if (segment.equals("temp")) { | ||
this.assemblyWriter.write( | ||
"@R" + Integer.toString(5 + c_index) + "\n" + "D=M\n" + "@SP\n" + "A=M\n" + "M=D\n" + advSP()); | ||
|
||
// push pointer | ||
} else if (segment.equals("pointer")) { | ||
this.assemblyWriter.write( | ||
"@" + Integer.toString(3 + c_index) + "\n" + "D=M\n" + "@SP\n" + "A=M\n" + "M=D\n" + advSP()); | ||
|
||
// push static | ||
} else if (segment.equals("static")) { | ||
this.assemblyWriter.write(staticName(c_index) + "D=M\n" + "@SP\n" + "A=M\n" + "M=D\n" + advSP()); | ||
|
||
} else { | ||
this.assemblyWriter.write("ERROR IN COMMAND PUSH"); | ||
} | ||
} | ||
|
||
private void handlePop(String segment, int c_index) throws IOException { | ||
|
||
this.assemblyWriter.write(chooseSeg(segment, c_index) + "D=A+D\n" + "@R13\n" + "M=D\n" + backSP() + "A=M\n" + "D=A\n" | ||
+ "@R13\n" + "A=M\n" + "M=D\n"); | ||
|
||
} | ||
|
||
public void close() throws IOException { | ||
this.assemblyWriter.write("(END)\n"); | ||
this.assemblyWriter.write("@END\n"); | ||
this.assemblyWriter.write("0;JMP\n"); | ||
this.assemblyWriter.close(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import java.io.IOException; | ||
|
||
public class Main { | ||
|
||
public static void main(String[] args) throws IOException { | ||
|
||
Parser parser = new Parser(args[0]); | ||
CodeWriter codeWriter = new CodeWriter(args[0]); | ||
|
||
while (parser.hasMoreCommands()) { | ||
parser.advance(); | ||
|
||
switch (parser.commandType()) { | ||
|
||
case 0: | ||
codeWriter.writeArithmetic(parser.arg1()); | ||
break; | ||
|
||
case 1: | ||
case 2: | ||
System.out.println(parser.commandType() + parser.arg1() + parser.arg2()); | ||
codeWriter.writePushPop(parser.commandType(), parser.arg1(), parser.arg2()); | ||
break; | ||
|
||
case 3: | ||
System.out.println(parser.arg1()); | ||
codeWriter.writeLabel(parser.arg1()); | ||
break; | ||
|
||
case 4: | ||
System.out.println(parser.arg1()); | ||
codeWriter.writeGo(parser.arg1()); | ||
break; | ||
|
||
case 5: | ||
System.out.println(parser.arg1()); | ||
codeWriter.writeIf(parser.arg1()); | ||
break; | ||
|
||
default: | ||
System.out.println("TODO"); | ||
return; | ||
} | ||
} | ||
codeWriter.close(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import java.io.BufferedReader; | ||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.io.FileReader; | ||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
|
||
class Parser { | ||
|
||
String[] currentCommand; | ||
BufferedReader myReader; | ||
File vmTranslate; | ||
String pathVM; | ||
private int currentLine = 0; | ||
private ArrayList<String> lines; | ||
public static final int ARITHMETIC = 0; | ||
public static final int PUSH = 1; | ||
public static final int POP = 2; | ||
public static final int LABEL = 3; | ||
public static final int GOTO = 4; | ||
public static final int IF = 5; | ||
public static final int FUNCTION = 6; | ||
public static final int RETURN = 7; | ||
public static final int CALL = 8; | ||
public static final ArrayList<String> arithmeticCmds = new ArrayList<String>(); | ||
|
||
static { | ||
|
||
arithmeticCmds.add("add"); | ||
arithmeticCmds.add("sub"); | ||
arithmeticCmds.add("neg"); | ||
arithmeticCmds.add("eq"); | ||
arithmeticCmds.add("gt"); | ||
arithmeticCmds.add("lt"); | ||
arithmeticCmds.add("and"); | ||
arithmeticCmds.add("or"); | ||
arithmeticCmds.add("not"); | ||
} | ||
|
||
public Parser(String pathVM) throws IOException { | ||
this.pathVM = pathVM; | ||
this.currentCommand = new String[3]; | ||
this.lines = new ArrayList<String>(); | ||
File vmCode = new File(this.pathVM); | ||
try { | ||
this.myReader = new BufferedReader(new FileReader(vmCode)); | ||
String line = this.myReader.readLine(); | ||
while (line != null) { | ||
line = line.replaceAll("//.+", ""); | ||
if (line.equals("")) { | ||
line = this.myReader.readLine(); | ||
continue; | ||
} | ||
this.lines.add(line); | ||
line = this.myReader.readLine(); | ||
} | ||
myReader.close(); | ||
} catch (FileNotFoundException e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
} | ||
|
||
public boolean hasMoreCommands() { | ||
return currentLine <= this.lines.size() - 1; | ||
} | ||
|
||
public void advance() { | ||
this.currentCommand = this.lines.get(currentLine).trim().split(" "); | ||
currentLine++; | ||
} | ||
|
||
public int commandType() { | ||
|
||
String currentType = this.currentCommand[0]; | ||
|
||
if (arithmeticCmds.contains(currentType)) { | ||
return ARITHMETIC; | ||
} else if (currentType.equals("push")) { | ||
return PUSH; | ||
} else if (currentType.equals("pop")) { | ||
return POP; | ||
} else if (currentType.equals("label")) { | ||
return LABEL; | ||
} else if (currentType.equals("goto")) { | ||
return GOTO; | ||
} else if (currentType.equals("if-goto")) { | ||
return IF; | ||
} else if (currentType.equals("function")) { | ||
return FUNCTION; | ||
} else if (currentType.equals("return")) { | ||
return RETURN; | ||
} else if (currentType.equals("call")) { | ||
return CALL; | ||
} | ||
|
||
System.out.println(currentType); | ||
return -1; | ||
} | ||
|
||
public String arg1() { | ||
|
||
if (this.commandType() == RETURN) { | ||
throw new IllegalStateException("RETURN command!"); | ||
} else if (this.commandType() == ARITHMETIC) { | ||
return this.currentCommand[0]; | ||
} else { | ||
return this.currentCommand[1]; | ||
} | ||
|
||
} | ||
|
||
public int arg2() { | ||
|
||
if (this.commandType() == PUSH | this.commandType() == POP | this.commandType() == CALL | ||
| this.commandType() == FUNCTION) { | ||
return Integer.parseInt(this.currentCommand[2]); | ||
} else { | ||
throw new IllegalArgumentException("Ilegal command!"); | ||
} | ||
} | ||
} |