public static void shell() throws Exception {
System.out.println("loOp (http://looplang.org)");
System.out.println(" by Dhanji R. Prasanna\n");
ConsoleReader reader = new ConsoleReader();
try {
reader.setExpandEvents(false);
reader.addCompleter(new MetaCommandCompleter());
Unit shellScope = new Unit(null, ModuleDecl.SHELL);
FunctionDecl main = new FunctionDecl("main", null);
shellScope.declare(main);
shellContext = new HashMap<String, Object>();
boolean inFunction = false;
// Used to build up multiline statement blocks (like functions)
StringBuilder block = null;
//noinspection InfiniteLoopStatement
do {
String prompt = (block != null) ? "| " : ">> ";
String rawLine = reader.readLine(prompt);
if (inFunction) {
if (rawLine == null || rawLine.trim().isEmpty()) {
inFunction = false;
// Eval the function to verify it.
printResult(Loop.evalClassOrFunction(block.toString(), shellScope));
block = null;
continue;
}
block.append(rawLine).append('\n');
continue;
}
if (rawLine == null) {
quit(reader);
}
//noinspection ConstantConditions
String line = rawLine.trim();
if (line.isEmpty())
continue;
// Add a require import.
if (line.startsWith("require ")) {
shellScope.declare(new LexprParser(new Tokenizer(line + '\n').tokenize()).require());
shellScope.loadDeps("<shell>");
continue;
}
if (line.startsWith(":q") || line.startsWith(":quit")) {
quit(reader);
}
if (line.startsWith(":h") || line.startsWith(":help")) {
printHelp();
}
if (line.startsWith(":run")) {
String[] split = line.split("[ ]+", 2);
if (split.length < 2 || !split[1].endsWith(".loop"))
System.out.println("You must specify a .loop file to run.");
Loop.run(split[1]);
continue;
}
if (line.startsWith(":r") || line.startsWith(":reset")) {
System.out.println("Context reset.");
shellScope = new Unit(null, ModuleDecl.SHELL);
main = new FunctionDecl("main", null);
shellScope.declare(main);
shellContext = new HashMap<String, Object>();
continue;
}
if (line.startsWith(":i") || line.startsWith(":imports")) {
for (RequireDecl requireDecl : shellScope.imports()) {
System.out.println(requireDecl.toSymbol());
}
System.out.println();
continue;
}
if (line.startsWith(":f") || line.startsWith(":functions")) {
for (FunctionDecl functionDecl : shellScope.functions()) {
StringBuilder args = new StringBuilder();
List<Node> children = functionDecl.arguments().children();
for (int i = 0, childrenSize = children.size(); i < childrenSize; i++) {
Node arg = children.get(i);
args.append(arg.toSymbol());
if (i < childrenSize - 1)
args.append(", ");
}
System.out.println(functionDecl.name()
+ ": (" + args.toString() + ")"
+ (functionDecl.patternMatching ? " #pattern-matching" : "")
);
}
System.out.println();
continue;
}
if (line.startsWith(":t") || line.startsWith(":type")) {
String[] split = line.split("[ ]+", 2);
if (split.length <= 1) {
System.out.println("Give me an expression to determine the type for.\n");
continue;
}
Object result = evalInFunction(split[1], main, shellScope, false);
printTypeOf(result);
continue;
}
if (line.startsWith(":javatype")) {
String[] split = line.split("[ ]+", 2);
if (split.length <= 1) {
System.out.println("Give me an expression to determine the type for.\n");
continue;
}
Object result = evalInFunction(split[1], main, shellScope, false);
if (result instanceof LoopError)
System.out.println(result.toString());
else
System.out.println(result == null ? "null" : result.getClass().getName());
continue;
}
// Function definitions can be multiline.
if (line.endsWith("->") || line.endsWith("=>")) {
inFunction = true;
block = new StringBuilder(line).append('\n');
continue;
} else if (isDangling(line)) {
if (block == null)
block = new StringBuilder();
block.append(line).append('\n');
continue;
}
if (block != null) {
rawLine = block.append(line).toString();
block = null;
}
// First determine what kind of expression this is.
main.children().clear();
// OK execute expression.
try {
printResult(evalInFunction(rawLine, main, shellScope, true));
} catch (ClassCastException e) {
StackTraceSanitizer.cleanForShell(e);
System.out.println("#error: " + e.getMessage());
System.out.println();
} catch (RuntimeException e) {
StackTraceSanitizer.cleanForShell(e);
e.printStackTrace();
System.out.println();
}
} while (true);
} catch (IOException e) {
System.err.println("Something went wrong =(");
reader.getTerminal().reset();
System.exit(1);
}
}