diff --git a/src/environment/RuntimeEnvironment.java b/src/environment/RuntimeEnvironment.java index 867f11d..628e20a 100644 --- a/src/environment/RuntimeEnvironment.java +++ b/src/environment/RuntimeEnvironment.java @@ -2,6 +2,8 @@ package environment; import java.io.*; +import error.ErrorManager; + public class RuntimeEnvironment { private static RuntimeEnvironment uniqueInstance = new RuntimeEnvironment(); @@ -10,13 +12,19 @@ public class RuntimeEnvironment { return uniqueInstance; } + private String inputName; private InputStream input; private PrintStream output; private PrintStream errorOutput; private Runnable terminationFunction; private Runnable errorTerminationFunction; + private ErrorManager errorManager; private RuntimeEnvironment() {} + + public void setInputName(String inputName) { + this.inputName = inputName; + } public void setInput(InputStream input) { this.input = input; @@ -37,15 +45,19 @@ public class RuntimeEnvironment { public void setErrorTerminationFunction(Runnable errorTerminationFunction) { this.errorTerminationFunction = errorTerminationFunction; } + + public void setErrorManager(ErrorManager errorManager) { + this.errorManager = errorManager; + } + + public String getInputName() { + return inputName; + } public InputStream getInput() { return input; } - public String getInputName() { - return input.toString(); - } - public PrintStream getOutput() { return output; } @@ -61,5 +73,9 @@ public class RuntimeEnvironment { public void terminateExceptionally() { errorTerminationFunction.run(); } + + public ErrorManager getErrorManager() { + return errorManager; + } } diff --git a/src/error/LispException.java b/src/error/LispException.java index 41e499b..e0feb9e 100644 --- a/src/error/LispException.java +++ b/src/error/LispException.java @@ -4,6 +4,18 @@ public abstract class LispException extends RuntimeException { private static final long serialVersionUID = 1L; + public static final LispException convertToLispException(RuntimeException e) { + return new LispException() { + + private static final long serialVersionUID = 1L; + + @Override + public String getMessage() { + return e.getMessage(); + } + }; + } + public int getSeverity() { return 0; } diff --git a/src/function/builtin/LOAD.java b/src/function/builtin/LOAD.java index 2036696..d50c46a 100644 --- a/src/function/builtin/LOAD.java +++ b/src/function/builtin/LOAD.java @@ -1,9 +1,12 @@ package function.builtin; +import static error.LispException.convertToLispException; + import java.io.*; import java.text.MessageFormat; import environment.RuntimeEnvironment; +import error.*; import function.*; import parser.LispParser; import sexpression.*; @@ -12,12 +15,14 @@ public class LOAD extends LispFunction { private ArgumentValidator argumentValidator; private RuntimeEnvironment environment; + private ErrorManager errorManager; public LOAD() { this.argumentValidator = new ArgumentValidator("LOAD"); this.argumentValidator.setExactNumberOfArguments(1); this.argumentValidator.setEveryArgumentExpectedType(LispString.class); this.environment = RuntimeEnvironment.getInstance(); + this.errorManager = this.environment.getErrorManager(); } public SExpression call(Cons argumentList) { @@ -49,7 +54,7 @@ public class LOAD extends LispFunction { try { parser = new LispParser(new FileInputStream(fileName), fileName); } catch (FileNotFoundException e) { - printCouldNotOpenFileMessage(fileName); + errorManager.generateError(new CouldNotLoadFileException(fileName)); } return parser; @@ -58,12 +63,12 @@ public class LOAD extends LispFunction { private boolean isSuccessfulEvaluation(LispParser parser) { while (!parser.isEof()) { try { - SExpression sexpr = parser.getNextSExpression(); - - EVAL.eval(sexpr); + EVAL.eval(parser.getNextSExpression()); + } catch (LispException e) { + errorManager.generateError(e); + return false; } catch (RuntimeException e) { - printErrorMessage(e.getMessage()); - + errorManager.generateError(convertToLispException(e)); return false; } } @@ -71,14 +76,19 @@ public class LOAD extends LispFunction { return true; } - private void printCouldNotOpenFileMessage(String fileName) { - String message = MessageFormat.format("could not open ''{0}''", fileName); - printErrorMessage(message); - } + public static class CouldNotLoadFileException extends LispException { - private void printErrorMessage(String errorMessage) { - String message = MessageFormat.format("LOAD: {0}", errorMessage); - environment.getErrorOutput().println(message); + private static final long serialVersionUID = 1L; + private String fileName; + + public CouldNotLoadFileException(String fileName) { + this.fileName = fileName; + } + + @Override + public String getMessage() { + return MessageFormat.format("could not load ''{0}''", fileName); + } } } diff --git a/src/interpreter/InteractiveLispInterpreter.java b/src/interpreter/InteractiveLispInterpreter.java index 7bc2698..14080a0 100644 --- a/src/interpreter/InteractiveLispInterpreter.java +++ b/src/interpreter/InteractiveLispInterpreter.java @@ -2,7 +2,7 @@ package interpreter; public class InteractiveLispInterpreter extends LispInterpreter { - private static final String GREETING = "SUNY Potsdam Lisp Interpreter - Version 4.4.3"; + private static final String GREETING = "SUNY Potsdam Lisp Interpreter - Version 1.0.0"; private static final String PROMPT = "~ "; @Override diff --git a/src/interpreter/LispInterpreter.java b/src/interpreter/LispInterpreter.java index 8a7de2d..006aa1b 100644 --- a/src/interpreter/LispInterpreter.java +++ b/src/interpreter/LispInterpreter.java @@ -1,6 +1,7 @@ package interpreter; -import java.io.*; +import static error.LispException.convertToLispException; + import java.text.MessageFormat; import environment.RuntimeEnvironment; @@ -14,26 +15,13 @@ public class LispInterpreter { public static final String ANSI_RESET = "\u001B[0m"; public static final String ANSI_GREEN = "\u001B[32m"; - private LispParser parser; - private ErrorManager errorManager; protected RuntimeEnvironment environment; + protected ErrorManager errorManager; + private LispParser parser; public LispInterpreter() { this.environment = RuntimeEnvironment.getInstance(); - this.errorManager = new ErrorManager(); - this.parser = new LispParser(this.environment.getInput(), this.environment.getInputName()); - } - - public LispInterpreter(String fileName) { - this.environment = RuntimeEnvironment.getInstance(); - this.errorManager = new ErrorManager(); - - try { - this.environment.setInput(new FileInputStream(fileName)); - } catch (FileNotFoundException e) { - this.errorManager.generateError(new LispFileNotFoundException(e)); - } - + this.errorManager = this.environment.getErrorManager(); this.parser = new LispParser(this.environment.getInput(), this.environment.getInputName()); } @@ -72,40 +60,8 @@ public class LispInterpreter { protected void erasePrompt() {} - private LispException convertToLispException(RuntimeException e) { - return new LispException() { - - private static final long serialVersionUID = 1L; - - @Override - public String getMessage() { - return e.getMessage(); - } - }; - } - protected void printFarewell() { environment.getOutput().println(); } - public static class LispFileNotFoundException extends LispException { - - private static final long serialVersionUID = 1L; - private String message; - - public LispFileNotFoundException(FileNotFoundException e) { - this.message = e.getMessage(); - } - - @Override - public int getSeverity() { - return ErrorManager.CRITICAL_LEVEL; - } - - @Override - public String getMessage() { - return message; - } - } - } diff --git a/src/interpreter/LispInterpreterBuilder.java b/src/interpreter/LispInterpreterBuilder.java index 2a37640..98c5b6b 100644 --- a/src/interpreter/LispInterpreterBuilder.java +++ b/src/interpreter/LispInterpreterBuilder.java @@ -4,6 +4,8 @@ import java.io.*; public interface LispInterpreterBuilder { + void setInputName(String inputName); + void setInput(InputStream inputStream); void setOutput(PrintStream outputStream); diff --git a/src/interpreter/LispInterpreterBuilderImpl.java b/src/interpreter/LispInterpreterBuilderImpl.java index f9ab7e1..20f30cb 100644 --- a/src/interpreter/LispInterpreterBuilderImpl.java +++ b/src/interpreter/LispInterpreterBuilderImpl.java @@ -13,23 +13,28 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { return uniqueInstance; } + private String inputName; private InputStream inputStream; private PrintStream outputStream; private PrintStream errorOutputStream; private Runnable terminationFunction; private Runnable errorTerminationFunction; private RuntimeEnvironment environment; - private String fileName; private boolean isInteractive; private boolean isBuilt; private LispInterpreterBuilderImpl() { this.environment = RuntimeEnvironment.getInstance(); - this.fileName = ""; + this.inputName = ""; this.isInteractive = true; this.isBuilt = false; } + @Override + public void setInputName(String inputName) { + this.inputName = inputName; + } + @Override public void setInput(InputStream inputStream) { this.inputStream = inputStream; @@ -58,7 +63,7 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { @Override public void useFile(String fileName) { - this.fileName = fileName; + this.inputName = fileName; this.isInteractive = false; } @@ -71,18 +76,40 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { } private LispInterpreter buildInterpreter() { - environment.setInput(inputStream); + configureRuntimeEnvironment(); + LispInterpreter lispInterpreter = createInterpreter(); + isBuilt = true; + + return lispInterpreter; + } + + private void configureRuntimeEnvironment() { + ErrorManager errorManager = new ErrorManager(); + environment.setOutput(outputStream); environment.setErrorOutput(errorOutputStream); environment.setTerminationFunction(terminationFunction); environment.setErrorTerminationFunction(errorTerminationFunction); + environment.setErrorManager(errorManager); + configureInput(errorManager); + } - LispInterpreter lispInterpreter = isInteractive ? new InteractiveLispInterpreter() - : new LispInterpreter(fileName); + private void configureInput(ErrorManager errorManager) { + environment.setInputName(inputName); - isBuilt = true; + try { + environment.setInput(getInputStream()); + } catch (FileNotFoundException e) { + errorManager.generateError(new LispFileNotFoundException(e)); + } + } - return lispInterpreter; + private InputStream getInputStream() throws FileNotFoundException { + return isInteractive ? inputStream : new FileInputStream(inputName); + } + + private LispInterpreter createInterpreter() { + return isInteractive ? new InteractiveLispInterpreter() : new LispInterpreter(); } public class InterpreterAlreadyBuiltException extends LispException { @@ -100,4 +127,24 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { } } + public static class LispFileNotFoundException extends LispException { + + private static final long serialVersionUID = 1L; + private String message; + + public LispFileNotFoundException(FileNotFoundException e) { + this.message = e.getMessage(); + } + + @Override + public int getSeverity() { + return ErrorManager.CRITICAL_LEVEL; + } + + @Override + public String getMessage() { + return message; + } + } + } diff --git a/src/main/LispMain.java b/src/main/LispMain.java index fa930bf..a91e510 100644 --- a/src/main/LispMain.java +++ b/src/main/LispMain.java @@ -13,16 +13,22 @@ public class LispMain { private static LispInterpreter buildInterpreter(String[] args) { LispInterpreterBuilder builder = LispInterpreterBuilderImpl.getInstance(); - builder.setInput(System.in); builder.setOutput(System.out); builder.setErrorOutput(System.err); builder.setTerminationFunction(() -> System.exit(0)); builder.setErrorTerminationFunction(() -> System.exit(1)); - - if (args.length > 0) - builder.useFile(args[0]); + configureInput(args, builder); return builder.build(); } + private static void configureInput(String[] args, LispInterpreterBuilder builder) { + if (args.length > 0) + builder.useFile(args[0]); + else { + builder.setInputName("stdin"); + builder.setInput(System.in); + } + } + } diff --git a/test/environment/RuntimeEnvironmentTester.java b/test/environment/RuntimeEnvironmentTester.java index a6add2b..0241c01 100644 --- a/test/environment/RuntimeEnvironmentTester.java +++ b/test/environment/RuntimeEnvironmentTester.java @@ -6,8 +6,10 @@ import java.util.*; import org.junit.*; +import error.ErrorManager; + public class RuntimeEnvironmentTester { - + private static final String TERMINATED_SUCCESSFULLY = "TERMINATED_SUCCESSFULLY"; private static final String TERMINATED_EXCEPTIONALLY = "TERMINATED_EXCEPTIONALLY"; @@ -23,12 +25,18 @@ public class RuntimeEnvironmentTester { this.indicatorSet = new HashSet<>(); } + @Test + public void assignInputName() { + this.environment.setInputName("test"); + + assertEquals("test", this.environment.getInputName()); + } + @Test public void assignInput() { this.environment.setInput(System.in); assertEquals(System.in, this.environment.getInput()); - assertEquals(System.in.toString(), this.environment.getInputName()); } @Test @@ -61,4 +69,12 @@ public class RuntimeEnvironmentTester { assertTrue(indicatorSet.contains(TERMINATED_EXCEPTIONALLY)); } + @Test + public void assignErrorManager() { + ErrorManager errorManager = new ErrorManager(); + this.environment.setErrorManager(errorManager); + + assertEquals(errorManager, this.environment.getErrorManager()); + } + } diff --git a/test/function/builtin/LOADTester.java b/test/function/builtin/LOADTester.java index 8ed723c..7b9d85b 100644 --- a/test/function/builtin/LOADTester.java +++ b/test/function/builtin/LOADTester.java @@ -1,6 +1,6 @@ package function.builtin; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import static testutil.TestUtilities.*; import java.io.*; @@ -15,12 +15,12 @@ public class LOADTester { private ByteArrayOutputStream outputStream; - private void assertPrinted(String expected) { - assertEquals(expected, outputStream.toString()); + private void assertSomethingPrinted() { + assertTrue(outputStream.toByteArray().length > 0); } private void assertNothingPrinted() { - assertPrinted(""); + assertTrue(outputStream.toByteArray().length == 0); } @Before @@ -42,7 +42,7 @@ public class LOADTester { String input = "(load \"test/function/builtin/test-files/load-bad.lisp\")"; assertSExpressionsMatch(Nil.getInstance(), evaluateString(input)); - assertPrinted("LOAD: expression begins with ')' - line 1, column 1\n"); + assertSomethingPrinted(); } @Test @@ -50,7 +50,7 @@ public class LOADTester { String input = "(load \"doesNotExist.lisp\")"; assertSExpressionsMatch(Nil.getInstance(), evaluateString(input)); - assertPrinted("LOAD: could not open 'doesNotExist.lisp'\n"); + assertSomethingPrinted(); } @Test(expected = BadArgumentTypeException.class)