package org.archstudio.prolog.console;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Map.Entry;
import org.archstudio.prolog.engine.MostGeneralUnifierEngine;
import org.archstudio.prolog.engine.PrologUtils;
import org.archstudio.prolog.engine.ProofContext;
import org.archstudio.prolog.engine.UnificationEngine;
import org.archstudio.prolog.op.Executable;
import org.archstudio.prolog.op.iso.Neck;
import org.archstudio.prolog.parser.PrologParser;
import org.archstudio.prolog.term.ComplexTerm;
import org.archstudio.prolog.term.Term;
import org.archstudio.prolog.term.VariableTerm;
import org.archstudio.sysutils.SystemUtils;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.IConsoleFactory;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IConsolePageParticipant;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleInputStream;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.part.IPageBookViewPage;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
public class PrologConsoleFactory implements IConsoleFactory {
public static final class StopExecutionAction extends Action {
private final IConsole console;
public StopExecutionAction(IConsole console) {
super("Stop Execution", ImageDescriptor.createFromImage(PlatformUI.getWorkbench().getSharedImages()
.getImage(ISharedImages.IMG_ELCL_STOP)));
this.console = console;
}
@Override
public void run() {
((ProofContext) ((IOConsole) console).getAttribute(ProofContext.class.getName())).cancel();
}
}
public static final class PageParticipant implements IConsolePageParticipant {
private StopExecutionAction stopExecutionAction;
@SuppressWarnings("all")
@Override
public Object getAdapter(Class adapter) {
return null;
}
@Override
public void init(IPageBookViewPage page, IConsole console) {
stopExecutionAction = new StopExecutionAction(console);
IToolBarManager manager = page.getSite().getActionBars().getToolBarManager();
manager.appendToGroup(IConsoleConstants.LAUNCH_GROUP, stopExecutionAction);
}
@Override
public void dispose() {
}
@Override
public void activated() {
}
@Override
public void deactivated() {
}
}
@Override
public void openConsole() {
openConsole(null);
}
public static void openConsole(ProofContext optionalProofContext) {
ConsolePlugin plugin = ConsolePlugin.getDefault();
IConsoleManager conMan = plugin.getConsoleManager();
IConsole[] existing = conMan.getConsoles();
for (IConsole console : existing) {
if (PrologConsoleFactory.class.getName().equals(console.getType())) {
conMan.removeConsoles(new IConsole[] { console });
}
}
// create a new one
IOConsole console = new IOConsole("Prolog", PrologConsoleFactory.class.getName(), null, true);
conMan.addConsoles(new IConsole[] { console });
hookUpProlog(console, optionalProofContext);
console.activate();
}
public static void hookUpProlog(final IOConsole console, ProofContext optionalProofContext) {
final IOConsoleInputStream in = console.getInputStream();
in.setColor(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN));
final BufferedReader inbr = new BufferedReader(new InputStreamReader(in));
final IOConsoleOutputStream prompt = console.newOutputStream();
prompt.setColor(Display.getDefault().getSystemColor(SWT.COLOR_BLUE));
final PrintWriter promptpw = new PrintWriter(prompt, true);
final IOConsoleOutputStream out = console.newOutputStream();
out.setColor(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
final PrintWriter outpw = new PrintWriter(out, true);
final IOConsoleOutputStream err = console.newOutputStream();
err.setColor(Display.getDefault().getSystemColor(SWT.COLOR_RED));
final PrintWriter errpw = new PrintWriter(err, true);
final ProofContext proofContext = optionalProofContext != null ? optionalProofContext : new ProofContext();
final UnificationEngine unificationEngine = new MostGeneralUnifierEngine();
console.setAttribute(ProofContext.class.getName(), proofContext);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
outpw.println("Welcome. Use :- to switch to INPUT mode and ?- to switch to QUERY mode.");
proofContext.setOutput(new BufferedWriter(new OutputStreamWriter(out)));
boolean inQueryMode = true;
MAIN: while (true) {
try {
if (inQueryMode) {
promptpw.print("[QUERY MODE] ?- ");
promptpw.flush();
String command = "";
while (true) {
String line = inbr.readLine().trim();
command += "\n" + line;
if (":-".equals(command.trim())) {
inQueryMode = false;
continue MAIN;
}
if (command.endsWith(".")) {
break;
}
}
proofContext.reset();
for (Term t : PrologParser.parseTerms(proofContext, command)) {
if (!(t instanceof Executable)) {
errpw.println("Not executable: ?- " + command);
continue;
}
int count = 1;
boolean firstResult = true;
for (Map<VariableTerm, Term> result : PrologUtils.execute(proofContext,
unificationEngine, t)) {
if (!firstResult) {
outpw.println(";");
}
firstResult = false;
if (result.isEmpty()) {
outpw.print("true");
}
else {
boolean firstVar = true;
String prefix = "" + count++ + ". ";
for (Entry<VariableTerm, Term> var : SystemUtils.sortedByKey(result.entrySet())) {
if (var.getKey().getName().startsWith("_G")) {
continue;
}
if (!firstVar) {
outpw.println();
outpw.print(Strings.repeat(" ", prefix.length()));
}
else {
outpw.print(prefix);
}
firstVar = false;
outpw.print(var.getKey() + " = " + var.getValue());
}
outpw.flush();
}
}
if (firstResult) {
outpw.print("false");
}
outpw.println(".");
outpw.flush();
if (proofContext.isCancelled()) {
errpw.println("Execution stopped.");
}
}
}
else {
promptpw.print("[INPUT MODE] > ");
promptpw.flush();
String command = "";
while (true) {
String line = inbr.readLine().trim();
command += "\n" + line;
if ("?-".equals(command.trim())) {
inQueryMode = true;
continue MAIN;
}
if (command.endsWith(".")) {
break;
}
}
proofContext.reset();
for (Term t : PrologParser.parseTerms(proofContext, command)) {
if (!(t instanceof ComplexTerm || t instanceof Neck)) {
errpw.println("Expecting a complex term or rule: " + command);
continue;
}
proofContext.add(Lists.newArrayList((ComplexTerm) t));
}
continue;
}
}
catch (IOException e) {
// console window was closed
proofContext.setOutput(new BufferedWriter(new OutputStreamWriter(System.out)));
return;
}
catch (Exception e) {
e.printStackTrace(errpw);
}
}
}
});
t.setName("Prolog Console");
t.setDaemon(true);
t.start();
}
}