From 5e0071169a9c9b46911c8a842a632cf4ab903289 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 21 Jun 2011 14:14:34 -0700 Subject: [PATCH] prolog-shell: Simple command line Prolog interpreter Since Prolog isn't the most popular language, define a small interactive interpreter that users or site administartors can play around with by downloading the Gerrit WAR file and executing: java -jar gerrit.war prolog-shell Change-Id: I0474b59e6ace24e6e6bfda58f574add3b2bf79e0 --- Documentation/pgm-index.txt | 3 + Documentation/pgm-prolog-shell.txt | 57 ++++++++++++ .../gerrit/launcher/GerritLauncher.java | 12 ++- .../com/google/gerrit/pgm/PrologShell.java | 93 +++++++++++++++++++ 4 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 Documentation/pgm-prolog-shell.txt create mode 100644 gerrit-pgm/src/main/java/com/google/gerrit/pgm/PrologShell.java diff --git a/Documentation/pgm-index.txt b/Documentation/pgm-index.txt index 353e90f1c5..4db4ab04ed 100644 --- a/Documentation/pgm-index.txt +++ b/Documentation/pgm-index.txt @@ -18,6 +18,9 @@ link:pgm-daemon.html[daemon]:: link:pgm-gsql.html[gsql]:: Administrative interface to idle database. +link:pgm-prolog-shell.html[prolog-shell]:: + Simple interactive Prolog interpreter. + link:pgm-rulec.html[rulec]:: Compile project-specific Prolog rules to JARs. diff --git a/Documentation/pgm-prolog-shell.txt b/Documentation/pgm-prolog-shell.txt new file mode 100644 index 0000000000..f3fa2d803c --- /dev/null +++ b/Documentation/pgm-prolog-shell.txt @@ -0,0 +1,57 @@ +prolog-shell +============ + +NAME +---- +prolog-shell - Simple interactive Prolog interpreter + +SYNOPSIS +-------- +[verse] +'java' -jar gerrit.war 'prolog-shell' [-s FILE.pl ...] + +DESCRIPTION +----------- +Provides a simple interactive Prolog interpreter for development +and testing. + +OPTIONS +------- +-s:: + Dynamically load the Prolog source code at startup, + as though the user had entered `['FILE.pl'].` into + the interepter once it was running. This option may + be supplied more than once to load multiple files. + +EXAMPLES +-------- +Define a simple predicate and test it: + +==== + $ cat >simple.pl + food(apple). + food(orange). + ^D + + $ java -jar gerrit.war prolog-shell -s simple.pl + Gerrit Code Review 2.2.1-84-ge9c3992 - Interactive Prolog Shell + based on Prolog Cafe 1.2.5 (mantis) + Copyright(C) 1997-2009 M.Banbara and N.Tamura + (type Ctrl-D or "halt." to exit, "['path/to/file.pl']." to load a file) + + {consulting /usr/local/google/users/sop/gerrit2/gerrit/simple.pl ...} + {/usr/local/google/users/sop/gerrit2/gerrit/simple.pl consulted 99 msec} + + | ?- food(Type). + + Type = apple ? ; + + Type = orange ? ; + + no + | ?- +==== + +GERRIT +------ +Part of link:index.html[Gerrit Code Review] diff --git a/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java index a097d75851..d9ea7d3e29 100644 --- a/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java +++ b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java @@ -120,7 +120,17 @@ public final class GerritLauncher { try { String cn = name; if (cn.equals(cn.toLowerCase())) { - cn = cn.substring(0, 1).toUpperCase() + cn.substring(1); + StringBuilder buf = new StringBuilder(); + buf.append(Character.toUpperCase(cn.charAt(0))); + for (int i = 1; i < cn.length(); i++) { + if (cn.charAt(i) == '-' && i + 1 < cn.length()) { + i++; + buf.append(Character.toUpperCase(cn.charAt(i))); + } else { + buf.append(cn.charAt(i)); + } + } + cn = buf.toString(); } clazz = Class.forName(pkg + "." + cn, true, loader); } catch (ClassNotFoundException cnfe) { diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/PrologShell.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/PrologShell.java new file mode 100644 index 0000000000..803b70252a --- /dev/null +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/PrologShell.java @@ -0,0 +1,93 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.pgm; + +import com.google.gerrit.pgm.util.AbstractProgram; + +import com.googlecode.prolog_cafe.lang.BufferingPrologControl; +import com.googlecode.prolog_cafe.lang.HaltException; +import com.googlecode.prolog_cafe.lang.Prolog; +import com.googlecode.prolog_cafe.lang.PrologClassLoader; +import com.googlecode.prolog_cafe.lang.PrologMain; +import com.googlecode.prolog_cafe.lang.SymbolTerm; + +import org.kohsuke.args4j.Option; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +public class PrologShell extends AbstractProgram { + @Option(name = "-s", multiValued = true, metaVar = "FILE.pl", usage = "file to load") + private List fileName = new ArrayList(); + + @Override + public int run() { + banner(); + + BufferingPrologControl pcl = new BufferingPrologControl(); + pcl.setPrologClassLoader(new PrologClassLoader(getClass().getClassLoader())); + pcl.setEnabled(EnumSet.allOf(Prolog.Feature.class), false); + pcl.setEnabled(Prolog.Feature.IO, true); + pcl.setEnabled(Prolog.Feature.STATISTICS_RUNTIME, true); + + pcl.initialize(Prolog.BUILTIN); + pcl.execute(Prolog.BUILTIN, "set_prolog_flag", + SymbolTerm.intern("print_stack_trace"), + SymbolTerm.intern("on")); + + for (String file : fileName) { + String path; + try { + path = new File(file).getCanonicalPath(); + } catch (IOException e) { + path = new File(file).getAbsolutePath(); + } + pcl.execute(Prolog.BUILTIN, "consult", SymbolTerm.create(path)); + System.err.println(); + System.err.flush(); + } + + try { + pcl.execute(Prolog.BUILTIN, "cafeteria"); + write("% halt\n"); + return 0; + } catch (HaltException halt) { + write("% halt(" + halt.getStatus() + ")\n"); + return halt.getStatus(); + } + } + + private void banner() { + System.err.format("Gerrit Code Review %s - Interactive Prolog Shell", + com.google.gerrit.common.Version.getVersion()); + System.err.println(); + System.err.println("based on " + PrologMain.VERSION); + System.err.println(" " + PrologMain.COPYRIGHT); + System.err.println("(type Ctrl-D or \"halt.\" to exit," + + " \"['path/to/file.pl'].\" to load a file)"); + System.err.println(); + System.err.flush(); + } + + private void write(String msg) { + System.out.flush(); + System.err.flush(); + System.out.println(msg); + System.out.flush(); + } +}