summaryrefslogtreecommitdiff
path: root/src/jvm/clojure
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-12-29 19:40:17 +0000
committerRich Hickey <richhickey@gmail.com>2008-12-29 19:40:17 +0000
commit49063a9bba42d14f83474802b3240f13e75bcb36 (patch)
tree0a1fb640c7d29169df84c86bed9b22bfa641d437 /src/jvm/clojure
parentdb598ed1a8d2105f552e1dcdaf2b37b781f015e0 (diff)
unified clojure.main, patch from Stephen C. Gilardi
Diffstat (limited to 'src/jvm/clojure')
-rw-r--r--src/jvm/clojure/lang/LineNumberingPushbackReader.java45
-rw-r--r--src/jvm/clojure/lang/Repl.java106
-rw-r--r--src/jvm/clojure/lang/Script.java68
-rw-r--r--src/jvm/clojure/main.java41
4 files changed, 91 insertions, 169 deletions
diff --git a/src/jvm/clojure/lang/LineNumberingPushbackReader.java b/src/jvm/clojure/lang/LineNumberingPushbackReader.java
index f722e867..ad81ce9a 100644
--- a/src/jvm/clojure/lang/LineNumberingPushbackReader.java
+++ b/src/jvm/clojure/lang/LineNumberingPushbackReader.java
@@ -18,6 +18,16 @@ import java.io.IOException;
public class LineNumberingPushbackReader extends PushbackReader{
+// This class is a PushbackReader that wraps a LineNumberReader. The code
+// here to handle line terminators only mentions '\n' because
+// LineNumberReader collapses all occurrences of CR, LF, and CRLF into a
+// single '\n'.
+
+private static final int newline = (int) '\n';
+
+private boolean _atLineStart = true;
+private boolean _prev;
+
public LineNumberingPushbackReader(Reader r){
super(new LineNumberReader(r));
}
@@ -26,7 +36,40 @@ public int getLineNumber(){
return ((LineNumberReader) in).getLineNumber() + 1;
}
+public int read() throws IOException{
+ int c = super.read();
+ _prev = _atLineStart;
+ _atLineStart = (c == newline) || (c == -1);
+ return c;
+}
+
+public void unread(int c) throws IOException{
+ super.unread(c);
+ _atLineStart = _prev;
+}
+
public String readLine() throws IOException{
- return ((LineNumberReader)in).readLine();
+ int c = read();
+ String line;
+ switch (c) {
+ case -1:
+ line = null;
+ break;
+ case newline:
+ line = "";
+ break;
+ default:
+ String first = String.valueOf((char) c);
+ String rest = ((LineNumberReader)in).readLine();
+ line = (rest == null) ? first : first + rest;
+ _prev = false;
+ _atLineStart = true;
+ break;
+ }
+ return line;
+}
+
+public boolean atLineStart(){
+ return _atLineStart;
}
}
diff --git a/src/jvm/clojure/lang/Repl.java b/src/jvm/clojure/lang/Repl.java
index 4a9153b2..9abe82aa 100644
--- a/src/jvm/clojure/lang/Repl.java
+++ b/src/jvm/clojure/lang/Repl.java
@@ -12,111 +12,11 @@
package clojure.lang;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
+import clojure.main;
-public class Repl{
-static final Symbol USER = Symbol.create("user");
-static final Symbol CLOJURE = Symbol.create("clojure.core");
-
-static final Var in_ns = RT.var("clojure.core", "in-ns");
-static final Var refer = RT.var("clojure.core", "refer");
-static final Var ns = RT.var("clojure.core", "*ns*");
-static final Var compile_path = RT.var("clojure.core", "*compile-path*");
-static final Var warn_on_reflection = RT.var("clojure.core", "*warn-on-reflection*");
-static final Var print_meta = RT.var("clojure.core", "*print-meta*");
-static final Var print_length = RT.var("clojure.core", "*print-length*");
-static final Var print_level = RT.var("clojure.core", "*print-level*");
-static final Var star1 = RT.var("clojure.core", "*1");
-static final Var star2 = RT.var("clojure.core", "*2");
-static final Var star3 = RT.var("clojure.core", "*3");
-static final Var stare = RT.var("clojure.core", "*e");
+class Repl {
public static void main(String[] args) throws Exception{
-
-// RT.init();
-
- try
- {
- //*ns* must be thread-bound for in-ns to work
- //thread-bind *warn-on-reflection* so it can be set!
- //thread-bind *1,*2,*3,*e so each repl has its own history
- //must have corresponding popThreadBindings in finally clause
- Var.pushThreadBindings(
- RT.map(ns, ns.get(),
- warn_on_reflection, warn_on_reflection.get(),
- print_meta, print_meta.get(),
- print_length, print_length.get(),
- print_level, print_level.get(),
- compile_path, "classes",
- star1, null,
- star2, null,
- star3, null,
- stare, null));
-
- //create and move into the user namespace
- in_ns.invoke(USER);
- refer.invoke(CLOJURE);
-
- //load any supplied files
- for(String file : RT.processCommandLine(args))
- try
- {
- Compiler.loadFile(file);
- }
- catch(Exception e)
- {
- e.printStackTrace((PrintWriter) RT.ERR.get());
- }
-
- //repl IO support
- LineNumberingPushbackReader rdr = new LineNumberingPushbackReader(new InputStreamReader(System.in, RT.UTF8));
- OutputStreamWriter w = (OutputStreamWriter) RT.OUT.get();//new OutputStreamWriter(System.out);
- Object EOF = new Object();
-
- //start the loop
- w.write("Clojure\n");
- for(; ;)
- {
- try
- {
- w.write(Compiler.currentNS().name + "=> ");
- w.flush();
- Object r = LispReader.read(rdr, false, EOF, false);
- if(r == EOF)
- {
- w.write("\n");
- w.flush();
- break;
- }
- Object ret = Compiler.eval(r);
- RT.print(ret, w);
- w.write('\n');
- //w.flush();
- star3.set(star2.get());
- star2.set(star1.get());
- star1.set(ret);
- }
- catch(Throwable e)
- {
- Throwable c = e;
- while(c.getCause() != null)
- c = c.getCause();
- ((PrintWriter) RT.ERR.get()).println(e instanceof Compiler.CompilerException ? e : c);
- stare.set(e);
- }
- }
- }
- catch(Exception e)
- {
- e.printStackTrace((PrintWriter) RT.ERR.get());
- }
- finally
- {
- Var.popThreadBindings();
- }
- System.exit(0);
+ main.legacy_repl(args);
}
-
}
diff --git a/src/jvm/clojure/lang/Script.java b/src/jvm/clojure/lang/Script.java
index e67f85e9..84abbe59 100644
--- a/src/jvm/clojure/lang/Script.java
+++ b/src/jvm/clojure/lang/Script.java
@@ -12,73 +12,11 @@
package clojure.lang;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.IOException;
-import java.util.List;
-import java.util.Arrays;
+import clojure.main;
-/**
- * <code>Script</code> provides a way to run one or more Clojure files
- * from a command line. Example usage:
- * <p>
- * <pre>java -cp clojure.jar script1.clj @/dir/script2.clj -- [arguments]</pre>
- * </p>
- * <p>
- * The example above will:
- * <ol>
- * <li>bind *command-line-args* to a seq containing the (optional) arguments provided
- * after the two dashes (--); this provides a way to provide command-line arguments
- * to your scripts</li>
- * <li>load the Clojure file <i>at the filesystem path</i> <code>script1.clj</code></li>
- * <li>load the Clojure file with the name <code>dir/script2.clj</code> <i>from the
- * current Java classpath</i>. Files to be loaded from the classpath must be prefixed
- * with a '@' character, and must be an "absolute path" to the classpath resource.
- * Note that the "path" will be treated as absolute within the classpath, whether it is
- * prefixed with a slash or not.</li>
- * </ol>
- * </p>
- * <p>
- * Any number of Clojure files can be provided as path arguments; these
- * files are loaded in order, as if via <code>load-file</code>. Filesystem and classpath
- * paths may be provided in any order, and be intermixed as necessary.
- * </p>
- * <p>
- * Once the final script path has been loaded, the java process exits.
- * </p>
- */
-public class Script{
+class Script {
public static void main(String[] args) throws Exception{
- try
- {
- for(String file : RT.processCommandLine(args))
- {
- if (file.startsWith("@"))
- {
- // trim leading slash if it's there -- loadResourceScript prepends its
- // own slash to every name it's given
- RT.loadResourceScript(file.substring(file.startsWith("@/") ? 2 : 1));
- }
- else
- {
- Compiler.loadFile(file);
- }
- }
- }
- finally
- {
- OutputStreamWriter w = (OutputStreamWriter) RT.OUT.get();
- try
- {
- w.flush();
- w.close();
- }
- catch(IOException e)
- {
- e.printStackTrace((PrintWriter)RT.ERR.get());
- }
- }
+ main.legacy_script(args);
}
}
-
diff --git a/src/jvm/clojure/main.java b/src/jvm/clojure/main.java
new file mode 100644
index 00000000..50bc3434
--- /dev/null
+++ b/src/jvm/clojure/main.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+ * which can be found in the file epl-v10.html at the root of this distribution.
+ * By using this software in any fashion, you are agreeing to be bound by
+ * the terms of this license.
+ * You must not remove this notice, or any other, from this software.
+ **/
+
+package clojure;
+
+import clojure.lang.Symbol;
+import clojure.lang.Namespace;
+import clojure.lang.Var;
+import clojure.lang.RT;
+
+public class main{
+
+final static private Symbol CLOJURE_MAIN = Symbol.create("clojure.main");
+final static private Namespace CLOJURE_MAIN_NS = Namespace.findOrCreate(CLOJURE_MAIN);
+final static private Var REQUIRE = Var.intern(RT.CLOJURE_NS, Symbol.create("require"));
+final static private Var LEGACY_REPL = Var.intern(CLOJURE_MAIN_NS, Symbol.create("legacy-repl"));
+final static private Var LEGACY_SCRIPT = Var.intern(CLOJURE_MAIN_NS, Symbol.create("legacy-script"));
+final static private Var MAIN = Var.intern(CLOJURE_MAIN_NS, Symbol.create("main"));
+
+public static void legacy_repl(String[] args) throws Exception{
+ REQUIRE.invoke(CLOJURE_MAIN);
+ LEGACY_REPL.invoke(RT.seq(args));
+}
+
+public static void legacy_script(String[] args) throws Exception{
+ REQUIRE.invoke(CLOJURE_MAIN);
+ LEGACY_SCRIPT.invoke(RT.seq(args));
+}
+
+public static void main(String[] args) throws Exception{
+ REQUIRE.invoke(CLOJURE_MAIN);
+ MAIN.applyTo(RT.seq(args));
+}
+}