Skip to content

Commit

Permalink
Implemented jump points
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicola Pfister committed Oct 6, 2016
1 parent 31c04c1 commit 3533f1f
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 18 deletions.
87 changes: 71 additions & 16 deletions src/JohnnyScript.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import com.sun.org.apache.bcel.internal.classfile.Code;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
Expand Down Expand Up @@ -68,8 +66,7 @@ private static String compile(String line) throws InvalidScriptException {
if (!nonComment.equals(""))
return encode(nonComment);
else return null;
}
else
} else
return encode(line);
}

Expand Down Expand Up @@ -163,17 +160,22 @@ public String getCode() {
class RamCode {

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

private static int writeIndex;

private ArrayList<String> code;
private Map<String, Integer> variables;
private Map<String, Integer> varLoc;
private Map<String, Integer> jumpPoints;
private Map<String, List<Integer>> jumps;

RamCode() {
code = new ArrayList<>();
variables = new LinkedHashMap<>();
varLoc = new LinkedHashMap<>();
jumpPoints = new LinkedHashMap<>();
jumps = new LinkedHashMap<>();
}

void addCode(String input) {
Expand All @@ -189,17 +191,38 @@ void addVar(String name, int value) throws DuplicateVariableException {
}
}

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

void addJumpPoint(String jpName) throws DuplicateJumpPointException {
if (jumpPoints.containsKey(jpName)) {
throw new DuplicateJumpPointException("Same jump point can't be set twice: " + jpName);
} else {
jumpPoints.put(jpName, code.size());
}
}

void addJump(String jpName) {
List<Integer> jumpLines;
if (jumps.containsKey(jpName)) {
jumpLines = jumps.get(jpName);
} else {
jumpLines = new ArrayList<>();
}
jumpLines.add(code.size());
jumps.put(jpName,jumpLines);

code.add(jpName + ":");
}

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

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

Expand All @@ -218,24 +241,42 @@ List getCode() {
output.set(writeIndex, generateLineZero());
writeIndex++;

variables.forEach((k,v) -> {
output.set(writeIndex, String.format("%03d",v));
variables.forEach((k, v) -> {
output.set(writeIndex, String.format("%03d", v));
writeIndex++;
});

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

List<String> invalid = new ArrayList<>();

jumps.forEach((jpName,jumpList) -> {
if(!jumpPoints.containsKey(jpName)) {
invalid.add(jpName);
} else {
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));
}
}
});

if (!invalid.isEmpty()) {
throw new InvalidJumpsException("Jumps to inexistent jump points: " + invalid.toString());
}

assert writeIndex == 1 + variables.size() + code.size();

return output;
}

private String generateLineZero() {
String firstLocAdress = String.format("%03d",variables.size()+1);
String firstLocAdress = String.format("%03d", variables.size() + 1);
return JohnnyScript.Codes.JMP.codeOrdinal + firstLocAdress;
}
}
Expand All @@ -256,7 +297,9 @@ class CompilerHaltException extends RuntimeException {

class DuplicateVariableException extends Exception {

DuplicateVariableException(String message) {super(message);}
DuplicateVariableException(String message) {
super(message);
}
}

class VariableNotInitializedException extends Exception {
Expand All @@ -265,3 +308,15 @@ class VariableNotInitializedException extends Exception {
super(message);
}
}

class DuplicateJumpPointException extends Exception {
DuplicateJumpPointException(String message) {
super(message);
}
}

class InvalidJumpsException extends Exception {
InvalidJumpsException(String message) {
super(message);
}
}
68 changes: 66 additions & 2 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.addVarRef(JohnnyScript.Codes.ADD.codeOrdinal+" #tst");
code.addCodeWithVar(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.addVarRef(JohnnyScript.Codes.ADD.codeOrdinal+" #tst");
code.addCodeWithVar(JohnnyScript.Codes.ADD.codeOrdinal+" #tst");

List codeList = code.getCode();

Expand All @@ -79,4 +79,68 @@ public void testAddVarRef() throws Exception {
assertEquals("000",codeList.get(i));
}
}

@Test
public void testAddJumpAfterJumpPoint() throws Exception {
RamCode code = new RamCode();
code.addJumpPoint("tst");
code.addJump("tst");

List codeList = code.getCode();

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

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

@Test
public void testAddJumpBeforeJumpPoint() throws Exception {
RamCode code = new RamCode();
code.addJump("tst");
code.addJumpPoint("tst");

List codeList = code.getCode();

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

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

@Test(expected = DuplicateJumpPointException.class)
public void testAddDuplicateJumpPoint() throws Exception {
RamCode code = new RamCode();
code.addJumpPoint("tst");
code.addJumpPoint("tst");
}

@Test(expected = InvalidJumpsException.class)
public void testInvalidJump() throws Exception {
RamCode code = new RamCode();
code.addJump(JohnnyScript.Codes.JMP.codeOrdinal + " tst");

code.getCode();
}

@Test
public void testProgram() throws Exception {
RamCode code = new RamCode();
code.addVar("z3", 0);
code.addCodeWithVar(JohnnyScript.Codes.NULL.codeOrdinal + "#z3");
code.addJumpPoint("start");
code.addCodeWithVar(JohnnyScript.Codes.TAKE.codeOrdinal + "#z3");
code.addVar("z1", 5);
code.addCodeWithVar(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.addJump("start");
code.addCode(JohnnyScript.Codes.HLT.codeOrdinal + "0");
}
}

0 comments on commit 3533f1f

Please sign in to comment.