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:
Mike Cifelli 2017-03-05 10:20:31 -05:00
parent c20bb682f2
commit 04cb46e94d
13 changed files with 206 additions and 50 deletions

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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) {}
}
}

View File

@ -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

View File

@ -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

View File

@ -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();
}
}

View File

@ -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

View File

@ -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();
}

View File

@ -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();
}