Store the base directory for an interpreted files
A bug was resolved where some functions were getting a null ErrorManager. A reset funtion was added to RuntimeEnvironment. Resolves #15
This commit is contained in:
parent
c20bb682f2
commit
04cb46e94d
|
@ -17,17 +17,35 @@ public class RuntimeEnvironment {
|
|||
private InputStream input;
|
||||
private PrintStream output;
|
||||
private PrintStream errorOutput;
|
||||
|
||||
private ErrorManager errorManager;
|
||||
private String path;
|
||||
private Runnable terminationFunction;
|
||||
private Runnable errorTerminationFunction;
|
||||
private Function<String, String> outputDecorator;
|
||||
private Function<String, String> valueOutputDecorator;
|
||||
private Function<String, String> warningOutputDecorator;
|
||||
private Function<String, String> errorOutputDecorator;
|
||||
private Function<String, String> criticalOutputDecorator;
|
||||
private Runnable terminationFunction;
|
||||
private Runnable errorTerminationFunction;
|
||||
private ErrorManager errorManager;
|
||||
|
||||
private RuntimeEnvironment() {}
|
||||
private RuntimeEnvironment() {
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
inputName = null;
|
||||
input = null;
|
||||
output = null;
|
||||
errorOutput = null;
|
||||
errorManager = null;
|
||||
path = null;
|
||||
terminationFunction = null;
|
||||
errorTerminationFunction = null;
|
||||
outputDecorator = null;
|
||||
valueOutputDecorator = null;
|
||||
warningOutputDecorator = null;
|
||||
errorOutputDecorator = null;
|
||||
criticalOutputDecorator = null;
|
||||
}
|
||||
|
||||
public void setInputName(String inputName) {
|
||||
this.inputName = inputName;
|
||||
|
@ -45,6 +63,14 @@ public class RuntimeEnvironment {
|
|||
this.errorOutput = errorOutput;
|
||||
}
|
||||
|
||||
public void setErrorManager(ErrorManager errorManager) {
|
||||
this.errorManager = errorManager;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public void setTerminationFunction(Runnable terminationFunction) {
|
||||
this.terminationFunction = terminationFunction;
|
||||
}
|
||||
|
@ -53,10 +79,6 @@ public class RuntimeEnvironment {
|
|||
this.errorTerminationFunction = errorTerminationFunction;
|
||||
}
|
||||
|
||||
public void setErrorManager(ErrorManager errorManager) {
|
||||
this.errorManager = errorManager;
|
||||
}
|
||||
|
||||
public void setOutputDecorator(Function<String, String> outputDecorator) {
|
||||
this.outputDecorator = outputDecorator;
|
||||
}
|
||||
|
@ -93,6 +115,14 @@ public class RuntimeEnvironment {
|
|||
return errorOutput;
|
||||
}
|
||||
|
||||
public ErrorManager getErrorManager() {
|
||||
return errorManager;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void terminateSuccessfully() {
|
||||
terminationFunction.run();
|
||||
}
|
||||
|
@ -101,10 +131,6 @@ public class RuntimeEnvironment {
|
|||
errorTerminationFunction.run();
|
||||
}
|
||||
|
||||
public ErrorManager getErrorManager() {
|
||||
return errorManager;
|
||||
}
|
||||
|
||||
public String decorateOutput(String output) {
|
||||
return outputDecorator.apply(output);
|
||||
}
|
||||
|
|
|
@ -18,14 +18,14 @@ import sexpression.*;
|
|||
public class LOAD extends LispFunction {
|
||||
|
||||
private ArgumentValidator argumentValidator;
|
||||
private ErrorManager errorManager;
|
||||
private RuntimeEnvironment environment;
|
||||
private Stack<String> pathPrefixes;
|
||||
|
||||
public LOAD() {
|
||||
this.argumentValidator = new ArgumentValidator("LOAD");
|
||||
this.argumentValidator.setExactNumberOfArguments(1);
|
||||
this.argumentValidator.setEveryArgumentExpectedType(LispString.class);
|
||||
this.errorManager = RuntimeEnvironment.getInstance().getErrorManager();
|
||||
this.environment = RuntimeEnvironment.getInstance();
|
||||
this.pathPrefixes = new Stack<>();
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,10 @@ public class LOAD extends LispFunction {
|
|||
}
|
||||
|
||||
private String prefixFileNameIfNecessary(String fileName) {
|
||||
return pathPrefixes.empty() ? fileName : pathPrefixes.peek() + fileName;
|
||||
if (pathPrefixes.isEmpty())
|
||||
return environment.getPath() + fileName;
|
||||
|
||||
return pathPrefixes.peek() + fileName;
|
||||
}
|
||||
|
||||
private LispParser attemptToCreateParserOnFile(String fileName) {
|
||||
|
@ -63,7 +66,7 @@ public class LOAD extends LispFunction {
|
|||
try {
|
||||
parser = new LispParser(new FileInputStream(fileName), fileName);
|
||||
} catch (FileNotFoundException e) {
|
||||
errorManager.handle(new CouldNotLoadFileWarning(fileName));
|
||||
this.environment.getErrorManager().handle(new CouldNotLoadFileWarning(fileName));
|
||||
}
|
||||
|
||||
return parser;
|
||||
|
@ -86,7 +89,7 @@ public class LOAD extends LispFunction {
|
|||
try {
|
||||
eval(parser.getNextSExpression());
|
||||
} catch (LispException e) {
|
||||
errorManager.handle(e);
|
||||
this.environment.getErrorManager().handle(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import static table.FunctionTable.*;
|
|||
import java.text.MessageFormat;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
import error.*;
|
||||
import error.LispWarning;
|
||||
import function.*;
|
||||
import sexpression.*;
|
||||
|
||||
|
@ -15,7 +15,7 @@ public abstract class Define extends LispSpecialFunction {
|
|||
private ArgumentValidator argumentValidator;
|
||||
private ArgumentValidator lambdaListIsListValidator;
|
||||
private ArgumentValidator lambdaListValidator;
|
||||
private ErrorManager errorManager;
|
||||
private RuntimeEnvironment environment;
|
||||
|
||||
public Define(String functionName) {
|
||||
this.argumentValidator = new ArgumentValidator(functionName);
|
||||
|
@ -28,7 +28,7 @@ public abstract class Define extends LispSpecialFunction {
|
|||
this.lambdaListValidator = new ArgumentValidator(functionName + "|parameter|");
|
||||
this.lambdaListValidator.setEveryArgumentExpectedType(Symbol.class);
|
||||
|
||||
this.errorManager = RuntimeEnvironment.getInstance().getErrorManager();
|
||||
this.environment = RuntimeEnvironment.getInstance();
|
||||
}
|
||||
|
||||
public SExpression call(Cons argumentList) {
|
||||
|
@ -46,7 +46,7 @@ public abstract class Define extends LispSpecialFunction {
|
|||
UserDefinedFunction function = createFunction(functionName, lambdaList, functionBody);
|
||||
|
||||
if (isAlreadyDefined(functionName.toString()))
|
||||
errorManager.handle(new RedefiningFunctionWarning(functionName.toString()));
|
||||
environment.getErrorManager().handle(new RedefiningFunctionWarning(functionName.toString()));
|
||||
|
||||
defineFunction(functionName.toString(), function);
|
||||
|
||||
|
|
|
@ -7,26 +7,26 @@ public class InteractiveLispInterpreter extends LispInterpreter {
|
|||
|
||||
@Override
|
||||
protected void printGreeting() {
|
||||
output.println(GREETING);
|
||||
output.println();
|
||||
environment.getOutput().println(GREETING);
|
||||
environment.getOutput().println();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayPrompt() {
|
||||
output.print(PROMPT);
|
||||
environment.getOutput().print(PROMPT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void erasePrompt() {
|
||||
for (int i = 0; i < PROMPT.length(); i++) {
|
||||
output.print("\b");
|
||||
environment.getOutput().print("\b");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void printFarewell() {
|
||||
output.println();
|
||||
output.println();
|
||||
environment.getOutput().println();
|
||||
environment.getOutput().println();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,24 +2,20 @@ package interpreter;
|
|||
|
||||
import static function.builtin.EVAL.eval;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.InputStream;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
import error.*;
|
||||
import error.LispException;
|
||||
import parser.LispParser;
|
||||
import sexpression.SExpression;
|
||||
|
||||
public class LispInterpreter {
|
||||
|
||||
protected RuntimeEnvironment environment;
|
||||
protected ErrorManager errorManager;
|
||||
protected PrintStream output;
|
||||
private LispParser parser;
|
||||
|
||||
public LispInterpreter() {
|
||||
this.environment = RuntimeEnvironment.getInstance();
|
||||
this.errorManager = this.environment.getErrorManager();
|
||||
this.output = environment.getOutput();
|
||||
}
|
||||
|
||||
public void setInput(InputStream input, String inputName) {
|
||||
|
@ -50,7 +46,7 @@ public class LispInterpreter {
|
|||
printValueOfNextSExpressionWithException();
|
||||
} catch (LispException e) {
|
||||
erasePrompt();
|
||||
errorManager.handle(e);
|
||||
environment.getErrorManager().handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,13 +55,13 @@ public class LispInterpreter {
|
|||
String result = environment.decorateValueOutput(String.valueOf(eval(sExpression)));
|
||||
|
||||
erasePrompt();
|
||||
output.println(result);
|
||||
environment.getOutput().println(result);
|
||||
}
|
||||
|
||||
protected void erasePrompt() {}
|
||||
|
||||
protected void printFarewell() {
|
||||
output.println();
|
||||
environment.getOutput().println();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -130,17 +130,29 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder {
|
|||
|
||||
environment.setOutput(outputStream);
|
||||
environment.setErrorOutput(errorOutputStream);
|
||||
environment.setErrorManager(errorManager);
|
||||
environment.setTerminationFunction(terminationFunction);
|
||||
environment.setErrorTerminationFunction(errorTerminationFunction);
|
||||
environment.setErrorManager(errorManager);
|
||||
environment.setOutputDecorator(outputDecorator);
|
||||
environment.setValueOutputDecorator(valueOutputDecorator);
|
||||
environment.setWarningOutputDecorator(warningOutputDecorator);
|
||||
environment.setErrorOutputDecorator(errorOutputDecorator);
|
||||
environment.setCriticalOutputDecorator(criticalOutputDecorator);
|
||||
configurePath();
|
||||
configureInput(errorManager);
|
||||
}
|
||||
|
||||
private void configurePath() {
|
||||
if (isFileBased)
|
||||
environment.setPath(getPathPrefix(inputName));
|
||||
else
|
||||
environment.setPath("");
|
||||
}
|
||||
|
||||
private String getPathPrefix(String fileName) {
|
||||
return fileName.substring(0, fileName.lastIndexOf(File.separator) + 1);
|
||||
}
|
||||
|
||||
private void configureInput(ErrorManager errorManager) {
|
||||
environment.setInputName(inputName);
|
||||
|
||||
|
|
|
@ -23,6 +23,12 @@ public class RuntimeEnvironmentTester {
|
|||
@Before
|
||||
public void setUp() {
|
||||
indicatorSet = new HashSet<>();
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -53,6 +59,21 @@ public class RuntimeEnvironmentTester {
|
|||
assertEquals(System.err, environment.getErrorOutput());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assignErrorManager() {
|
||||
ErrorManager errorManager = new ErrorManager();
|
||||
environment.setErrorManager(errorManager);
|
||||
|
||||
assertEquals(errorManager, environment.getErrorManager());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assignPath() {
|
||||
environment.setPath("testpath/");
|
||||
|
||||
assertEquals("testpath/", environment.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assignTerminationFunction() {
|
||||
environment.setTerminationFunction(() -> indicatorSet.add(TERMINATED_SUCCESSFULLY));
|
||||
|
@ -69,14 +90,6 @@ public class RuntimeEnvironmentTester {
|
|||
assertTrue(indicatorSet.contains(TERMINATED_EXCEPTIONALLY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assignErrorManager() {
|
||||
ErrorManager errorManager = new ErrorManager();
|
||||
environment.setErrorManager(errorManager);
|
||||
|
||||
assertEquals(errorManager, environment.getErrorManager());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assignOutputDecorator() {
|
||||
environment.setOutputDecorator(s -> "[" + s + "]");
|
||||
|
@ -112,4 +125,64 @@ public class RuntimeEnvironmentTester {
|
|||
assertEquals("/test/", environment.decorateCriticalOutput("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resetWorks() {
|
||||
environment.setInputName("test");
|
||||
environment.setInput(System.in);
|
||||
environment.setOutput(System.out);
|
||||
environment.setErrorOutput(System.err);
|
||||
environment.setErrorManager(new ErrorManager());
|
||||
environment.setPath("testpath/");
|
||||
environment.setTerminationFunction(() -> indicatorSet.add(TERMINATED_SUCCESSFULLY));
|
||||
environment.setErrorTerminationFunction(() -> indicatorSet.add(TERMINATED_EXCEPTIONALLY));
|
||||
environment.setOutputDecorator(s -> "[" + s + "]");
|
||||
environment.setValueOutputDecorator(s -> "(" + s + ")");
|
||||
environment.setWarningOutputDecorator(s -> "|" + s + "|");
|
||||
environment.setErrorOutputDecorator(s -> "{" + s + "}");
|
||||
environment.setCriticalOutputDecorator(s -> "/" + s + "/");
|
||||
environment.reset();
|
||||
|
||||
assertNull(environment.getInputName());
|
||||
assertNull(environment.getInput());
|
||||
assertNull(environment.getOutput());
|
||||
assertNull(environment.getErrorOutput());
|
||||
assertNull(environment.getErrorManager());
|
||||
assertNull(environment.getPath());
|
||||
|
||||
try {
|
||||
environment.terminateSuccessfully();
|
||||
fail("terminateSuccessfully");
|
||||
} catch (NullPointerException e) {}
|
||||
|
||||
try {
|
||||
environment.terminateExceptionally();
|
||||
fail("terminateExceptionally");
|
||||
} catch (NullPointerException e) {}
|
||||
|
||||
try {
|
||||
environment.decorateOutput("");
|
||||
fail("decorateOutput");
|
||||
} catch (NullPointerException e) {}
|
||||
|
||||
try {
|
||||
environment.decorateValueOutput("");
|
||||
fail("decorateValueOutput");
|
||||
} catch (NullPointerException e) {}
|
||||
|
||||
try {
|
||||
environment.decorateWarningOutput("");
|
||||
fail("decorateWarningOutput");
|
||||
} catch (NullPointerException e) {}
|
||||
|
||||
try {
|
||||
environment.decorateErrorOutput("");
|
||||
fail("decorateErrorOutput");
|
||||
} catch (NullPointerException e) {}
|
||||
|
||||
try {
|
||||
environment.decorateCriticalOutput("");
|
||||
fail("decorateCriticalOutput");
|
||||
} catch (NullPointerException e) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -82,6 +82,12 @@ public class ErrorManagerTester {
|
|||
indicatorSet = new HashSet<>();
|
||||
errorOutputStream = new ByteArrayOutputStream();
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -13,8 +13,13 @@ import function.ArgumentValidator.TooManyArgumentsException;
|
|||
public class EXITTester {
|
||||
|
||||
private static final String TERMINATED = "terminated";
|
||||
private RuntimeEnvironment environment;
|
||||
private Set<String> indicatorSet;
|
||||
|
||||
public EXITTester() {
|
||||
this.environment = RuntimeEnvironment.getInstance();
|
||||
}
|
||||
|
||||
private void assertTerminated() {
|
||||
assertTrue(indicatorSet.contains(TERMINATED));
|
||||
}
|
||||
|
@ -26,7 +31,13 @@ public class EXITTester {
|
|||
@Before
|
||||
public void setUp() {
|
||||
indicatorSet = new HashSet<>();
|
||||
RuntimeEnvironment.getInstance().setTerminationFunction(() -> indicatorSet.add(TERMINATED));
|
||||
environment.reset();
|
||||
environment.setTerminationFunction(() -> indicatorSet.add(TERMINATED));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -42,14 +42,21 @@ public class LOADTester {
|
|||
outputStream = new ByteArrayOutputStream();
|
||||
errorOutputStream = new ByteArrayOutputStream();
|
||||
|
||||
environment.reset();
|
||||
environment.setOutput(new PrintStream(outputStream));
|
||||
environment.setErrorOutput(new PrintStream(errorOutputStream));
|
||||
environment.setErrorManager(new ErrorManager());
|
||||
environment.setPath("");
|
||||
environment.setOutputDecorator(s -> s);
|
||||
environment.setWarningOutputDecorator(s -> s);
|
||||
environment.setErrorOutputDecorator(s -> s);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadGoodFile_ReturnsTAndPrintsNothing() {
|
||||
String input = "(load \"test/function/builtin/test-files/load-good.lisp\")";
|
||||
|
@ -105,4 +112,13 @@ public class LOADTester {
|
|||
evaluateString("(load)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUsesRuntimePath() {
|
||||
environment.setPath("test/function/builtin/test-files/nested/one/");
|
||||
String input = "(load \"load-one.lisp\")";
|
||||
|
||||
assertT(evaluateString(input));
|
||||
assertNothingPrinted();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,8 +13,13 @@ import function.ArgumentValidator.*;
|
|||
|
||||
public class PRINTTester {
|
||||
|
||||
private RuntimeEnvironment environment;
|
||||
private ByteArrayOutputStream outputStream;
|
||||
|
||||
public PRINTTester() {
|
||||
this.environment = RuntimeEnvironment.getInstance();
|
||||
}
|
||||
|
||||
private void assertPrinted(String expected) {
|
||||
assertEquals(expected, outputStream.toString());
|
||||
}
|
||||
|
@ -22,7 +27,13 @@ public class PRINTTester {
|
|||
@Before
|
||||
public void setUp() {
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
RuntimeEnvironment.getInstance().setOutput(new PrintStream(outputStream));
|
||||
environment.reset();
|
||||
environment.setOutput(new PrintStream(outputStream));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -30,15 +30,16 @@ public class DEFINE_MACROTester {
|
|||
public void setUp() {
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
|
||||
environment.reset();
|
||||
environment.setOutput(new PrintStream(outputStream));
|
||||
environment.setErrorManager(new ErrorManager());
|
||||
environment.setWarningOutputDecorator(s -> s);
|
||||
|
||||
resetFunctionTable();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
environment.reset();
|
||||
resetFunctionTable();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,15 +30,16 @@ public class DEFUNTester {
|
|||
public void setUp() {
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
|
||||
environment.reset();
|
||||
environment.setOutput(new PrintStream(outputStream));
|
||||
environment.setErrorManager(new ErrorManager());
|
||||
environment.setWarningOutputDecorator(s -> s);
|
||||
|
||||
resetFunctionTable();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
environment.reset();
|
||||
resetFunctionTable();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue