Skip to content

Commit

Permalink
adapted tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicola Pfister committed Oct 6, 2016
1 parent 3533f1f commit a97704d
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 81 deletions.
113 changes: 68 additions & 45 deletions src/JohnnyScript.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,60 +14,86 @@ public class JohnnyScript {

private static final String OUTPUT_EXTENSION = ".ram";
private static final String LINE_COMMENT_DELIMITER = "//";
private static final String JUMP_POINT_DELIMITER = ":";
private static final String VARIABLE_DELIMITER = "#";

public static void main(String[] args) throws IOException {

Path source = getFilename(args);
List<String> code = Files.readAllLines(source);
writeOutFile(source.getFileName().toString(), compileCode(code));
try {
writeOutFile(source.getFileName().toString(), compileCode(code));
} catch (Exception e) {
throw new CompilerHaltException("Compiler halted due to erroneous code!\n", e);
}

}

/**
* Generates the ram code consisting from 1000 lines of compiled JohnnyScript and "000" for empty lines
* Generates ram code using RamCode object
*
* @param sourceLines {@link java.util.List} of String objects containing lines of JohnnyScript code
* @param sourceLines {@link List} of String objects containing lines of JohnnyScript code
* @return compiled numeric code for .ram file
*/
private static List<String> compileCode(List<String> sourceLines) {
List<String> compiled = new ArrayList<>();

for (int i = 0; i <= 999; i++) {
if (i < sourceLines.size()) {
try {
String compiledLine = compile(sourceLines.get(i));
if (compiledLine != null) {
compiled.add(compiledLine);
} else {
sourceLines.remove(i); // Remove comment line from source
i--; // Reduce index to continue at next line without skipping
}
} catch (InvalidScriptException e) {
throw new CompilerHaltException("Invalid code at line " + i, e);
private static List<String> compileCode(List<String> sourceLines) throws InvalidScriptException, DuplicateVariableException, VariableNotInitializedException, DuplicateJumpPointException {
RamCode code = new RamCode();
int lineNumber = 0;
for (String line:sourceLines) {
line = decomment(line);
if (line == null) {
continue;
}
if (line.contains(VARIABLE_DELIMITER)) {
String[] parts = line.split(VARIABLE_DELIMITER + "| ");
if (parts[0].length() == 0) {
// variable declaration (# at start of line)
if(parts.length != 3) {
throw new InvalidScriptException("Syntax error at line " + lineNumber + ": " + line + " (variable declaration: #varname [int])");
} else code.addVar(parts[1],Integer.valueOf(parts[2]));
} else {
// reference to variable
if(parts.length != 3) {
throw new InvalidScriptException("Syntax error at line " + lineNumber + ": " + line + " (variable declaration: #varname [int])");
} else code.addCodeWithVar(encode(parts[0], false),parts[2]);
}
} else compiled.add("000");
} else {
if (line.contains(JUMP_POINT_DELIMITER)) {
String jpName = line.replace(":", "");
code.addJumpPoint(jpName);
} else {
String[] parts = line.split(" ");
if(Codes.valueOf(parts[0].toUpperCase()).codeOrdinal == Codes.JMP.codeOrdinal) {
code.addJump(parts[1]);
} else code.addCode(encode(line, true));
}

}
lineNumber++;

}

return compiled;
try {
return code.getCode();
} catch (InvalidJumpsException e) {
throw new CompilerHaltException("Compiler halted due to erroneous code!\n", e);
}
}

/**
* Handles compiling of specific lines depending on the type of code.
* Removes comments from line and trims excess whitespace
*
* @param line Line of JohnnyScript code
* @return compiled line of .ram code or null if line is a comment
* @throws InvalidScriptException on invalid JohnnyScript code
*/
private static String compile(String line) throws InvalidScriptException {
private static String decomment(String line) {
if (line.contains(LINE_COMMENT_DELIMITER)) {
/* Separate code from comment */
int commentStart = line.indexOf(LINE_COMMENT_DELIMITER);
String nonComment = line.substring(0, commentStart);
if (!nonComment.equals(""))
return encode(nonComment);
return nonComment.trim();
else return null;
} else
return encode(line);
} else return line.trim();
}

/**
Expand All @@ -77,17 +103,19 @@ private static String compile(String line) throws InvalidScriptException {
* @return numeric line for instruction
* @throws InvalidScriptException on invalid JohnnyScript code
*/
private static String encode(String line) throws InvalidScriptException {
String[] parts = line.trim().split(" ");
if (parts.length > 2) throw new InvalidScriptException("InvalidJohnnyScript (too many parts): " + line);
private static String encode(String line, boolean appendLow) throws InvalidScriptException {
String[] parts = line.split(" ");
if (parts.length > 2) throw new InvalidScriptException("Syntax error (too many parts): " + line);
if (parts.length == 1) {
return String.format("%03d", Integer.parseInt(parts[0]));
String output = Codes.valueOf(parts[0].toUpperCase()).getCode();
if (appendLow) output = output + "000";
return output;
} else {
String code = parts[0].toUpperCase();
String hi = Codes.valueOf(code).getCode();
String lo = String.format("%03d", Integer.parseInt(parts[1]));
return hi + lo;
}
// else there are two parts
String code = parts[0].toUpperCase();
String lo = String.format("%03d", Integer.parseInt(parts[1]));
String hi = Codes.valueOf(code).getCode();
return hi + lo;

}

Expand Down Expand Up @@ -160,7 +188,6 @@ public String getCode() {
class RamCode {

private static final int MAX_LINES = 999;
private static final String JUMP_POINT_DELIMITER = ":";

private static int writeIndex;

Expand Down Expand Up @@ -191,16 +218,12 @@ void addVar(String name, int value) throws DuplicateVariableException {
}
}

void addCodeWithVar(String input) throws VariableNotInitializedException {
assert input.contains("#");
String[] parts = input.split("#");
assert parts.length == 2;
String var = parts[1];
void addCodeWithVar(String commandOrdinal, String var) throws VariableNotInitializedException {
if (!variables.containsKey(var)) {
throw new VariableNotInitializedException("Variable has not been initialized: " + var);
} else {
int line = varLoc.get(var);
code.add(parts[0].trim() + String.format("%03d", line));
code.add(commandOrdinal + String.format("%03d", line));
}
}

Expand Down Expand Up @@ -232,7 +255,7 @@ private List<String> initializeZeros(List<String> code) {
return code;
}

List getCode() throws InvalidJumpsException {
List<String> getCode() throws InvalidJumpsException {
List<String> output = new ArrayList<>();
initializeZeros(output);

Expand All @@ -248,7 +271,7 @@ List getCode() throws InvalidJumpsException {

for (String loc : code
) {
output.add(writeIndex, loc);
output.set(writeIndex, loc);
writeIndex++;
}

Expand All @@ -261,7 +284,7 @@ List getCode() throws InvalidJumpsException {
for (int line:jumpList) {
line = 1 + variables.size() + line;
assert output.get(line).equals(jpName + ":");
output.set(line, JohnnyScript.Codes.JMP.codeOrdinal + String.format("%03d", line));
output.set(line, JohnnyScript.Codes.JMP.codeOrdinal + String.format("%03d", 1+variables.size()+jumpPoints.get(jpName)));
}
}
});
Expand Down
41 changes: 15 additions & 26 deletions test/JohnnyScriptTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,13 @@ public void commentLine() throws Exception {
List<String> outLines = Files.readAllLines(outputPath);

testCode = new ArrayList<>();
testCode.add("5001");
testCode.add("2000");
testCode.add("2000");

assertEquals(1000, outLines.size());
for (int i = 0; i < testCode.size(); i++) {
assertEquals("Line " + i, testCode.get(i),outLines.get(i));
}

testZeroLines(testCode.size(), outLines);

}

@Test
Expand All @@ -107,17 +104,25 @@ public void commentInline() throws Exception {
List<String> outLines = Files.readAllLines(outputPath);

testCode = new ArrayList<>();
testCode.add("5001");
testCode.add("2000");
testCode.add("2001");
testCode.add("2000");

assertEquals(1000, outLines.size());
for (int i = 0; i < testCode.size(); i++) {
assertEquals("Line " + i, testCode.get(i),outLines.get(i));
}

testZeroLines(testCode.size(), outLines);
}

@Test
public void testMaxLines() throws Exception {
List<String> testCode = new ArrayList<>();
Files.write(inputPath, testCode);

JohnnyScript.main(new String[]{validFile});
List<String> outLines = Files.readAllLines(outputPath);
assertEquals(1000, outLines.size());
}

@Test
Expand All @@ -137,10 +142,6 @@ public void testSave() throws Exception {
exhTest("SAVE");
}
@Test
public void testJmp() throws Exception {
exhTest("JMP");
}
@Test
public void testTst() throws Exception {
exhTest("TST");
}
Expand All @@ -161,23 +162,12 @@ public void testHlt() throws Exception {
exhTest("HLT");
}

/**
* Checks if lines after code are correctly filled with "000"
* @param i start index of "000" lines
* @param testCode code to test
*/
private void testZeroLines(int i, List<String> testCode) {
for (;i < 1000; i++) {
assertEquals("000",testCode.get(i));
}
}

/**
* Tests conversion of all possible addresses for a code
* @param code Code to test
*/
private void exhTest(String code) throws Exception {
for (int i = 0; i < 1000; i++) {
for (int i = 0; i < 999; i++) {
List<String> testCode = new ArrayList<>();
testCode.add(code + " " + i);
Files.write(inputPath, testCode);
Expand All @@ -189,12 +179,11 @@ private void exhTest(String code) throws Exception {
testCode = new ArrayList<>();
testCode.add(JohnnyScript.Codes.valueOf(code).getCode()+ String.format("%03d",i));

assertEquals(1000, outLines.size());
for (int j = 0; j < testCode.size(); j++) {
assertEquals("Line " + 0, "5001",outLines.get(0));

for (int j = 1; j < testCode.size(); j++) {
assertEquals("Line " + j, testCode.get(j),outLines.get(j));
}

testZeroLines(testCode.size(),outLines);
}
}
}
40 changes: 30 additions & 10 deletions test/RamCodeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void testAddVar() throws Exception {
@Test(expected = VariableNotInitializedException.class)
public void testAddVarRefWithoutInit() throws Exception {
RamCode code = new RamCode();
code.addCodeWithVar(JohnnyScript.Codes.ADD.codeOrdinal+" #tst");
code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.ADD.codeOrdinal), "tst");
}

@Test(expected = DuplicateVariableException.class)
Expand All @@ -67,7 +67,7 @@ public void testAddDuplicateVar() throws Exception {
public void testAddVarRef() throws Exception {
RamCode code = new RamCode();
code.addVar("tst",5);
code.addCodeWithVar(JohnnyScript.Codes.ADD.codeOrdinal+" #tst");
code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.ADD.codeOrdinal), "tst");

List codeList = code.getCode();

Expand Down Expand Up @@ -105,7 +105,7 @@ public void testAddJumpBeforeJumpPoint() throws Exception {
List codeList = code.getCode();

assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "001",codeList.get(0));
assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "001",codeList.get(1));
assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "002",codeList.get(1));

for (int i = 2; i < 1000; i++) {
assertEquals("000",codeList.get(i));
Expand All @@ -131,16 +131,36 @@ public void testInvalidJump() throws Exception {
public void testProgram() throws Exception {
RamCode code = new RamCode();
code.addVar("z3", 0);
code.addCodeWithVar(JohnnyScript.Codes.NULL.codeOrdinal + "#z3");
code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.NULL.codeOrdinal),"z3");
code.addJumpPoint("start");
code.addCodeWithVar(JohnnyScript.Codes.TAKE.codeOrdinal + "#z3");
code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.TAKE.codeOrdinal), "z3");
code.addVar("z1", 5);
code.addCodeWithVar(JohnnyScript.Codes.ADD.codeOrdinal + "#z1");
code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.ADD.codeOrdinal), "z1");
code.addVar("z2", 3);
code.addCodeWithVar(JohnnyScript.Codes.SAVE.codeOrdinal + "#z2");
code.addCodeWithVar(JohnnyScript.Codes.DEC.codeOrdinal + "#z1");
code.addCodeWithVar(JohnnyScript.Codes.TST.codeOrdinal + "#z1");
code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.SAVE.codeOrdinal), "z2");
code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.DEC.codeOrdinal), "z1");
code.addCodeWithVar(String.valueOf(JohnnyScript.Codes.TST.codeOrdinal), "z1");
code.addJump("start");
code.addCode(JohnnyScript.Codes.HLT.codeOrdinal + "0");
code.addCode(JohnnyScript.Codes.HLT.codeOrdinal + "000");

List codeList = code.getCode();

assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "004",codeList.get(0)); //jump to first program line
assertEquals("000",codeList.get(1)); //z3
assertEquals("005",codeList.get(2)); //z1
assertEquals("003",codeList.get(3)); //z2
assertEquals(JohnnyScript.Codes.NULL.codeOrdinal + "001",codeList.get(4));
assertEquals(JohnnyScript.Codes.TAKE.codeOrdinal + "001",codeList.get(5)); // jump point start set to here
assertEquals(JohnnyScript.Codes.ADD.codeOrdinal + "002",codeList.get(6));
assertEquals(JohnnyScript.Codes.SAVE.codeOrdinal + "003",codeList.get(7));
assertEquals(JohnnyScript.Codes.DEC.codeOrdinal + "002",codeList.get(8));
assertEquals(JohnnyScript.Codes.TST.codeOrdinal + "002",codeList.get(9));
assertEquals(JohnnyScript.Codes.JMP.codeOrdinal + "005",codeList.get(10));
assertEquals(JohnnyScript.Codes.HLT.codeOrdinal + "000",codeList.get(11));


for (int i = 12; i < 1000; i++) {
assertEquals("000",codeList.get(i));
}
}
}

0 comments on commit a97704d

Please sign in to comment.