diff --git a/src/pp/s1184725/boppi/BoppiGenerator.java b/src/pp/s1184725/boppi/BoppiGenerator.java index 006cc1a..875f819 100644 --- a/src/pp/s1184725/boppi/BoppiGenerator.java +++ b/src/pp/s1184725/boppi/BoppiGenerator.java @@ -1,10 +1,9 @@ package pp.s1184725.boppi; -import java.nio.file.Files; import java.util.*; import java.util.logging.Logger; -import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.tree.*; import org.apache.commons.lang3.StringUtils; @@ -101,11 +100,12 @@ public class BoppiGenerator extends BoppiBaseVisitor { protected BoppiGenerator(Annotations annotations, Logger logger) { try { - String memlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("memlib.iloc"))); //$NON-NLS-1$ + CharStream memlib = ToolChain.getCharStream(this.getClass(), "memlib.iloc"); //$NON-NLS-1$ prog = Assembler.instance().assemble(memlib); - String stdlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("stdlib.iloc"))); //$NON-NLS-1$ + CharStream stdlib = ToolChain.getCharStream(this.getClass(), "stdlib.iloc"); //$NON-NLS-1$ Program prog2 = Assembler.instance().assemble(stdlib); + try { for (Instr instr : prog2.getInstr()) prog.addInstr(instr); @@ -768,7 +768,7 @@ public class BoppiGenerator extends BoppiBaseVisitor { emit("loop or break", OpCode.cbr, temp1, cond, end); //$NON-NLS-1$ emit("end equality check", end, OpCode.nop); //$NON-NLS-1$ - + if (ops.get(ctx.op.getType()).equals(OpCode.cmp_NE)) emit("invert equality", OpCode.cmp_EQ, temp1, RegisterPool.ZERO, temp1); //$NON-NLS-1$ }); @@ -901,7 +901,8 @@ public class BoppiGenerator extends BoppiBaseVisitor { Reg addr = visit(expr); emit("save to var " + expr.getText(), OpCode.cstore, temp, addr); //$NON-NLS-1$ }); - else if (an.types.get(expr) instanceof ArrayType && SimpleType.CHAR.equals(((ArrayType)an.types.get(expr)).getType())) + else if (an.types.get(expr) instanceof ArrayType + && SimpleType.CHAR.equals(((ArrayType) an.types.get(expr)).getType())) res = regPool.withReg((temp) -> { emit("call stdsin", OpCode.loadI, new Num(prog.size() + 3), temp); //$NON-NLS-1$ emit("call stdsin", OpCode.push, temp); //$NON-NLS-1$ @@ -1044,7 +1045,7 @@ public class BoppiGenerator extends BoppiBaseVisitor { emit("push 1", OpCode.push, temp); //$NON-NLS-1$ emit("print character", OpCode.cout, new Str("")); //$NON-NLS-1$ //$NON-NLS-2$ }); - } else if (type instanceof ArrayType && SimpleType.CHAR.equals(((ArrayType)type).getType())) { + } else if (type instanceof ArrayType && SimpleType.CHAR.equals(((ArrayType) type).getType())) { regPool.withReg((temp) -> { emit("call stdsout", OpCode.loadI, new Num(prog.size() + 4), temp); //$NON-NLS-1$ emit("call stdsout", OpCode.push, temp); //$NON-NLS-1$ diff --git a/src/pp/s1184725/boppi/ToolChain.java b/src/pp/s1184725/boppi/ToolChain.java index 8c73aeb..a2f8c7a 100644 --- a/src/pp/s1184725/boppi/ToolChain.java +++ b/src/pp/s1184725/boppi/ToolChain.java @@ -5,6 +5,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.util.*; import java.util.logging.*; +import java.util.stream.Collectors; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.tree.*; @@ -24,7 +25,7 @@ public class ToolChain { /** * The file system path of this class */ - public static final Path PATH = Paths.get("src/" + ToolChain.class.getPackage().getName().replaceAll("\\.", "/")); + public static final Path PATH = Paths.get(ToolChain.class.getPackage().getName().replaceAll("\\.", "/")); /** * The last virtual machine used for executing a program */ @@ -197,7 +198,7 @@ public class ToolChain { } /** - * Opens a file for reading and returns its charstream. Throws an unhandled + * Opens a file for reading and returns its charstream. Throws an unchecked * exception if the file could not be read. * * @param file @@ -223,6 +224,29 @@ public class ToolChain { return CharStreams.fromString(code); } + /** + * Opens a file relative to the specified class and returns its charstream. + * Throws an unchecked exception if the file could not be read. + * + * @param basePath + * class to use as a base folder + * @param filename + * the name of the file + * @return a {@link CharStream} to be used in the lexer phase + */ + public static CharStream getCharStream(Class basePath, String filename) { + InputStream inputStream = basePath.getResourceAsStream(filename); + + if (inputStream == null) + throw new RuntimeException(new IOException()); + + try { + return CharStreams.fromStream(inputStream); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + /** * Generates ILOC code for an annotated program. * @@ -317,4 +341,29 @@ public class ToolChain { return log; } + + /** + * Reads a text file relative to the specified class and returns it as + * string. + * + * @param basePath + * class to use as a base folder + * @param filename + * the name of the file + * @return the contents of the file + * @throws IOException + * if the file could not be found or read + */ + public static String readBundledFile(Class basePath, String filename) throws IOException { + InputStream inputStream = basePath.getResourceAsStream(filename); + + if (inputStream == null) + throw new IOException(); + + try { + return new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n")); + } catch (UncheckedIOException e) { + throw new IOException(e); + } + } } diff --git a/src/pp/s1184725/boppi/test/ArrayTest.java b/src/pp/s1184725/boppi/test/ArrayTest.java index e30e350..525b6b7 100644 --- a/src/pp/s1184725/boppi/test/ArrayTest.java +++ b/src/pp/s1184725/boppi/test/ArrayTest.java @@ -16,7 +16,7 @@ public class ArrayTest { */ @Test public void correctArrayParsing() { - BoppiTests.parseFile("simpleArray.boppi"); + BoppiTests.parseFile("programs/simpleArray.boppi"); assertThat(BoppiTests.log, empty()); } @@ -46,7 +46,7 @@ public class ArrayTest { */ @Test public void correctArrayChecking() { - BoppiTests.checkFile("simpleArray.boppi"); + BoppiTests.checkFile("programs/simpleArray.boppi"); assertThat(BoppiTests.log, is(empty())); } @@ -96,12 +96,12 @@ public class ArrayTest { assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("7"))); - BoppiTests.compileAndRunFile("simpleArray.boppi"); + BoppiTests.compileAndRunFile("programs/simpleArray.boppi"); assertThat(BoppiTests.vm.getInterrupt(), is(0)); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("9", "H", "a", "Y"))); - BoppiTests.compileAndRunFile("complexArray.boppi"); + BoppiTests.compileAndRunFile("programs/complexArray.boppi"); assertThat(BoppiTests.vm.getInterrupt(), is(0)); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("1337", "13", "2", "15"))); @@ -116,7 +116,7 @@ public class ArrayTest { assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("true", "false", "false", "true"))); - BoppiTests.compileAndRunFile("arrayFunctions.boppi", "Hello"); + BoppiTests.compileAndRunFile("programs/arrayFunctions.boppi", "Hello"); assertThat(BoppiTests.vm.getInterrupt(), is(0)); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("Hi;Hello;1337"))); diff --git a/src/pp/s1184725/boppi/test/BoppiTests.java b/src/pp/s1184725/boppi/test/BoppiTests.java index 73649eb..119f0b2 100644 --- a/src/pp/s1184725/boppi/test/BoppiTests.java +++ b/src/pp/s1184725/boppi/test/BoppiTests.java @@ -1,6 +1,5 @@ package pp.s1184725.boppi.test; -import java.nio.file.*; import java.util.List; import java.util.logging.*; @@ -26,12 +25,6 @@ import pp.s1184725.boppi.*; @SuiteClasses({ ExpressionTest.class, SimpleVariableTest.class, ConditionalTest.class, SimpleFunctionTest.class, ClosureTest.class, ArrayTest.class }) public class BoppiTests { - /** - * The path for test programs - */ - public static final Path TEST_PROGRAM_LOCATION = Paths - .get("src/" + BoppiTests.class.getPackage().getName().replaceAll("\\.", "/") + "/programs/"); - /** * The default logging level */ @@ -100,7 +93,7 @@ public class BoppiTests { * the file name */ public static void parseFile(String file) { - parse(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file))); + parse(ToolChain.getCharStream(BoppiTests.class, file)); } private static void parse(CharStream stream) { @@ -128,7 +121,7 @@ public class BoppiTests { * the file name */ public static void checkFile(String file) { - check(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file))); + check(ToolChain.getCharStream(BoppiTests.class, file)); } private static void check(CharStream stream) { @@ -162,7 +155,7 @@ public class BoppiTests { * lines of input for the program */ public static void compileAndRunFile(String file, String... input) { - compileAndRun(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file)), String.join("\n", input) + "\n"); + compileAndRun(ToolChain.getCharStream(BoppiTests.class, file), String.join("\n", input) + "\n"); } private static void compileAndRun(CharStream stream, String input) { @@ -206,7 +199,7 @@ public class BoppiTests { * lines of input for the program */ public static void debugRunFile(String file, String... input) { - debugRun(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file)), String.join("\n", input) + "\n"); + debugRun(ToolChain.getCharStream(BoppiTests.class, file), String.join("\n", input) + "\n"); } /** diff --git a/src/pp/s1184725/boppi/test/ClosureTest.java b/src/pp/s1184725/boppi/test/ClosureTest.java index 854aac3..2e54078 100644 --- a/src/pp/s1184725/boppi/test/ClosureTest.java +++ b/src/pp/s1184725/boppi/test/ClosureTest.java @@ -20,10 +20,10 @@ public class ClosureTest { */ @Test public void correctClosureParsing() { - BoppiTests.parseFile("closure1.boppi"); + BoppiTests.parseFile("programs/closure1.boppi"); assertThat(BoppiTests.log, is(empty())); - BoppiTests.parseFile("closure2.boppi"); + BoppiTests.parseFile("programs/closure2.boppi"); assertThat(BoppiTests.log, is(empty())); } @@ -32,10 +32,10 @@ public class ClosureTest { */ @Test public void correctClosureChecking() { - BoppiTests.checkFile("closure1.boppi"); + BoppiTests.checkFile("programs/closure1.boppi"); assertThat(BoppiTests.log, is(empty())); - BoppiTests.checkFile("closure2.boppi"); + BoppiTests.checkFile("programs/closure2.boppi"); assertThat(BoppiTests.log, is(empty())); } @@ -44,22 +44,22 @@ public class ClosureTest { */ @Test public void correctClosureGeneration() { - BoppiTests.compileAndRunFile("closure1.boppi"); + BoppiTests.compileAndRunFile("programs/closure1.boppi"); assertThat(BoppiTests.vm.getInterrupt(), is(0)); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("8", "9"))); - BoppiTests.compileAndRunFile("closure2.boppi"); + BoppiTests.compileAndRunFile("programs/closure2.boppi"); assertThat(BoppiTests.vm.getInterrupt(), is(0)); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("8", "7", "15", "2"))); - BoppiTests.compileAndRunFile("closure3.boppi"); + BoppiTests.compileAndRunFile("programs/closure3.boppi"); assertThat(BoppiTests.vm.getInterrupt(), is(0)); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("7", "15", "2"))); - BoppiTests.compileAndRunFile("fibonacciRecursive.boppi", "1", "20", "30", "31", "0"); + BoppiTests.compileAndRunFile("programs/fibonacciRecursive.boppi", "1", "20", "30", "31", "0"); assertThat(BoppiTests.vm.getInterrupt(), is(0)); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining(Integer.toString(fib(1)), Integer.toString(fib(20)), @@ -73,13 +73,13 @@ public class ClosureTest { @Ignore("Disabled as long as closures do not nicely clean memory.") @Test public void correctClosureCleanup() { - BoppiTests.compileAndRunFile("closure1.boppi"); + BoppiTests.compileAndRunFile("programs/closure1.boppi"); assertThat(BoppiTests.vm.load(0), is(4)); - BoppiTests.compileAndRunFile("closure2.boppi"); + BoppiTests.compileAndRunFile("programs/closure2.boppi"); assertThat(BoppiTests.vm.load(0), is(4)); - BoppiTests.compileAndRunFile("closure3.boppi"); + BoppiTests.compileAndRunFile("programs/closure3.boppi"); assertThat(BoppiTests.vm.load(0), is(4)); } diff --git a/src/pp/s1184725/boppi/test/ConditionalTest.java b/src/pp/s1184725/boppi/test/ConditionalTest.java index 5bd1c42..2244245 100644 --- a/src/pp/s1184725/boppi/test/ConditionalTest.java +++ b/src/pp/s1184725/boppi/test/ConditionalTest.java @@ -16,10 +16,10 @@ public class ConditionalTest { */ @Test public void correctConditionalParsing() { - BoppiTests.parseFile("if.boppi"); + BoppiTests.parseFile("programs/if.boppi"); assertThat(BoppiTests.log, empty()); - BoppiTests.parseFile("while.boppi"); + BoppiTests.parseFile("programs/while.boppi"); assertThat(BoppiTests.log, empty()); } @@ -28,10 +28,10 @@ public class ConditionalTest { */ @Test public void correctConditionalChecking() { - BoppiTests.checkFile("if.boppi"); + BoppiTests.checkFile("programs/if.boppi"); assertThat(BoppiTests.log, is(empty())); - BoppiTests.checkFile("while.boppi"); + BoppiTests.checkFile("programs/while.boppi"); assertThat(BoppiTests.log, is(empty())); } @@ -55,11 +55,11 @@ public class ConditionalTest { */ @Test public void basicPrograms() { - BoppiTests.compileAndRunFile("basicProgram1.boppi", "1", "T"); + BoppiTests.compileAndRunFile("programs/basicProgram1.boppi", "1", "T"); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("T", "T"))); - BoppiTests.compileAndRunFile("fibonacciIterative.boppi", "6"); + BoppiTests.compileAndRunFile("programs/fibonacciIterative.boppi", "6"); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("13"))); } diff --git a/src/pp/s1184725/boppi/test/ExpressionTest.java b/src/pp/s1184725/boppi/test/ExpressionTest.java index b44899b..1f07515 100644 --- a/src/pp/s1184725/boppi/test/ExpressionTest.java +++ b/src/pp/s1184725/boppi/test/ExpressionTest.java @@ -22,7 +22,7 @@ public class ExpressionTest { */ @Test public void correctExpressionParsing() { - BoppiTests.parseFile("simpleExpression.boppi"); + BoppiTests.parseFile("programs/simpleExpression.boppi"); assertThat(BoppiTests.log, empty()); } @@ -52,7 +52,7 @@ public class ExpressionTest { */ @Test public void correctExpressionChecking() { - BoppiTests.checkFile("simpleExpression.boppi"); + BoppiTests.checkFile("programs/simpleExpression.boppi"); assertThat(BoppiTests.log, is(empty())); } @@ -90,7 +90,7 @@ public class ExpressionTest { assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("T", "e", "s", "t", "!"))); - BoppiTests.compileAndRunFile("simpleExpression.boppi"); + BoppiTests.compileAndRunFile("programs/simpleExpression.boppi"); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("1", "1", "3", "A", "false"))); diff --git a/src/pp/s1184725/boppi/test/ILOCAllocatorTest.java b/src/pp/s1184725/boppi/test/ILOCAllocatorTest.java index 8c46479..b735e73 100644 --- a/src/pp/s1184725/boppi/test/ILOCAllocatorTest.java +++ b/src/pp/s1184725/boppi/test/ILOCAllocatorTest.java @@ -1,7 +1,5 @@ package pp.s1184725.boppi.test; -import java.nio.file.Files; - import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import org.junit.Test; @@ -9,6 +7,7 @@ import org.junit.Test; import pp.iloc.*; import pp.iloc.eval.Machine; import pp.iloc.model.Program; +import pp.s1184725.boppi.*; /** * Tests for the ILOC simple allocator (memlib.iloc). @@ -75,8 +74,7 @@ public class ILOCAllocatorTest { private void sim(String code) { try { - String memlib = new String( - Files.readAllBytes(BoppiTests.TEST_PROGRAM_LOCATION.resolve("../../memlib.iloc"))); + String memlib = ToolChain.readBundledFile(BoppiGenerator.class, "memlib.iloc"); Program program = Assembler.instance().assemble(memlib + "\n" + code); vm = new Machine(); vm.setSize((FREEMEM + FIRSTSLOT + HEADER) * 2); diff --git a/src/pp/s1184725/boppi/test/SimpleFunctionTest.java b/src/pp/s1184725/boppi/test/SimpleFunctionTest.java index 7683a54..aa78002 100644 --- a/src/pp/s1184725/boppi/test/SimpleFunctionTest.java +++ b/src/pp/s1184725/boppi/test/SimpleFunctionTest.java @@ -140,7 +140,7 @@ public class SimpleFunctionTest { assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("A"))); - BoppiTests.compileAndRunFile("simpleProcedure.boppi", "8"); + BoppiTests.compileAndRunFile("programs/simpleProcedure.boppi", "8"); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("5", "16"))); } @@ -154,11 +154,11 @@ public class SimpleFunctionTest { BoppiTests.compileAndRunString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}; 0"); assertThat(BoppiTests.log, is(empty())); - BoppiTests.compileAndRunFile("recursiveFactorial.boppi", "5"); + BoppiTests.compileAndRunFile("programs/recursiveFactorial.boppi", "5"); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("120"))); - BoppiTests.compileAndRunFile("simpleFunctionPassing.boppi"); + BoppiTests.compileAndRunFile("programs/simpleFunctionPassing.boppi"); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("40", "104", "1", "2", "8"))); } diff --git a/src/pp/s1184725/boppi/test/SimpleVariableTest.java b/src/pp/s1184725/boppi/test/SimpleVariableTest.java index 1dc5c72..8b06f02 100644 --- a/src/pp/s1184725/boppi/test/SimpleVariableTest.java +++ b/src/pp/s1184725/boppi/test/SimpleVariableTest.java @@ -16,7 +16,7 @@ public class SimpleVariableTest { */ @Test public void correctVariableParsing() { - BoppiTests.parseFile("simpleVariable.boppi"); + BoppiTests.parseFile("programs/simpleVariable.boppi"); assertThat(BoppiTests.log, empty()); } @@ -49,7 +49,7 @@ public class SimpleVariableTest { */ @Test public void correctScopeParsing() { - BoppiTests.parseFile("simpleScope.boppi"); + BoppiTests.parseFile("programs/simpleScope.boppi"); assertThat(BoppiTests.log, empty()); } @@ -58,7 +58,7 @@ public class SimpleVariableTest { */ @Test public void correctVariableChecking() { - BoppiTests.checkFile("simpleVariable.boppi"); + BoppiTests.checkFile("programs/simpleVariable.boppi"); assertThat(BoppiTests.log, is(empty())); BoppiTests.checkString("var const int x; x := 3; var x y; y := x;"); @@ -101,7 +101,7 @@ public class SimpleVariableTest { */ @Test public void correctScopeChecking() { - BoppiTests.checkFile("simpleScope.boppi"); + BoppiTests.checkFile("programs/simpleScope.boppi"); assertThat(BoppiTests.log, is(empty())); } @@ -133,10 +133,10 @@ public class SimpleVariableTest { assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("12", "4"))); - BoppiTests.compileAndRunFile("simpleVariable.boppi"); + BoppiTests.compileAndRunFile("programs/simpleVariable.boppi"); assertThat(BoppiTests.log, is(empty())); - BoppiTests.compileAndRunFile("simpleScope.boppi"); + BoppiTests.compileAndRunFile("programs/simpleScope.boppi"); assertThat(BoppiTests.out, is(arrayContaining("9", "4", "true"))); assertThat(BoppiTests.log, is(empty())); }