119 lines
3.5 KiB
Java
119 lines
3.5 KiB
Java
package function.builtin;
|
|
|
|
import static function.builtin.EVAL.eval;
|
|
import static java.text.MessageFormat.format;
|
|
import static sexpression.Nil.NIL;
|
|
import static sexpression.Symbol.T;
|
|
import static util.Path.getPathPrefix;
|
|
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.util.Stack;
|
|
|
|
import environment.RuntimeEnvironment;
|
|
import error.LispException;
|
|
import error.LispWarning;
|
|
import function.ArgumentValidator;
|
|
import function.FunctionNames;
|
|
import function.LispFunction;
|
|
import parser.LispParser;
|
|
import sexpression.Cons;
|
|
import sexpression.LispString;
|
|
import sexpression.SExpression;
|
|
|
|
@FunctionNames({ "LOAD" })
|
|
public class LOAD extends LispFunction {
|
|
|
|
private static Stack<String> pathPrefixes = new Stack<>();
|
|
private ArgumentValidator argumentValidator;
|
|
private RuntimeEnvironment environment;
|
|
|
|
public LOAD(String name) {
|
|
this.argumentValidator = new ArgumentValidator(name);
|
|
this.argumentValidator.setExactNumberOfArguments(1);
|
|
this.argumentValidator.setEveryArgumentExpectedType(LispString.class);
|
|
this.environment = RuntimeEnvironment.getInstance();
|
|
}
|
|
|
|
@Override
|
|
public SExpression call(Cons argumentList) {
|
|
argumentValidator.validate(argumentList);
|
|
|
|
LispString quotedName = (LispString) argumentList.getFirst();
|
|
String fileName = removeSurroundingQuotes(quotedName.toString());
|
|
|
|
return processFile(fileName);
|
|
}
|
|
|
|
private String removeSurroundingQuotes(String fileName) {
|
|
return fileName.substring(1, (fileName.length() - 1));
|
|
}
|
|
|
|
private SExpression processFile(String fileName) {
|
|
boolean isSuccessful = false;
|
|
String prefixedFileName = prefixFileNameIfNecessary(fileName);
|
|
LispParser parser = attemptToCreateParserOnFile(prefixedFileName);
|
|
|
|
if (parser != null)
|
|
isSuccessful = isSuccessfulEvaluationWithPathPrefix(prefixedFileName, parser);
|
|
|
|
return isSuccessful ? T : NIL;
|
|
}
|
|
|
|
private String prefixFileNameIfNecessary(String fileName) {
|
|
if (pathPrefixes.isEmpty())
|
|
return environment.getPath() + fileName;
|
|
|
|
return pathPrefixes.peek() + fileName;
|
|
}
|
|
|
|
private LispParser attemptToCreateParserOnFile(String fileName) {
|
|
LispParser parser = null;
|
|
|
|
try {
|
|
parser = new LispParser(new FileInputStream(fileName), fileName);
|
|
} catch (FileNotFoundException e) {
|
|
environment.getErrorManager().handle(new CouldNotLoadFileWarning(fileName));
|
|
}
|
|
|
|
return parser;
|
|
}
|
|
|
|
private boolean isSuccessfulEvaluationWithPathPrefix(String prefixedFileName, LispParser parser) {
|
|
pathPrefixes.push(getPathPrefix(prefixedFileName));
|
|
boolean isSuccessful = isSuccessfulEvaluation(parser);
|
|
pathPrefixes.pop();
|
|
|
|
return isSuccessful;
|
|
}
|
|
|
|
private boolean isSuccessfulEvaluation(LispParser parser) {
|
|
while (!parser.isEof()) {
|
|
try {
|
|
eval(parser.getNextSExpression());
|
|
} catch (LispException e) {
|
|
environment.getErrorManager().handle(e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static class CouldNotLoadFileWarning extends LispWarning {
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
private String fileName;
|
|
|
|
public CouldNotLoadFileWarning(String fileName) {
|
|
this.fileName = fileName;
|
|
}
|
|
|
|
@Override
|
|
public String getMessage() {
|
|
return format("could not load ''{0}''", fileName);
|
|
}
|
|
}
|
|
|
|
}
|