summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml1
-rw-r--r--src/clj/clojure/core.clj20
-rw-r--r--src/clj/clojure/main.clj35
-rw-r--r--src/clj/clojure/reflect.clj123
-rw-r--r--src/clj/clojure/reflect/java.clj253
-rw-r--r--src/clj/clojure/repl.clj33
-rw-r--r--src/jvm/clojure/lang/Compiler.java142
-rw-r--r--src/jvm/clojure/lang/LispReader.java38
-rw-r--r--src/jvm/clojure/lang/PersistentQueue.java22
-rw-r--r--src/jvm/clojure/lang/RT.java328
-rw-r--r--src/jvm/clojure/lang/Symbol.java8
-rw-r--r--src/jvm/clojure/lang/Var.java4
-rw-r--r--test/clojure/test_clojure.clj1
-rw-r--r--test/clojure/test_clojure/data_structures.clj73
-rw-r--r--test/clojure/test_clojure/ns_libs.clj8
-rw-r--r--test/clojure/test_clojure/reflect.clj33
16 files changed, 779 insertions, 343 deletions
diff --git a/build.xml b/build.xml
index 2cb38650..e7261e5b 100644
--- a/build.xml
+++ b/build.xml
@@ -120,6 +120,7 @@
<arg value="clojure.java.browse-ui"/>
<arg value="clojure.string"/>
<arg value="clojure.data"/>
+ <arg value="clojure.reflect"/>
</java>
</target>
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index b399f6cf..2f5504cc 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -3755,19 +3755,23 @@
(defn ns-resolve
"Returns the var or Class to which a symbol will be resolved in the
- namespace, else nil. Note that if the symbol is fully qualified,
- the var/Class to which it resolves need not be present in the
- namespace."
+ namespace (unless found in the environement), else nil. Note that
+ if the symbol is fully qualified, the var/Class to which it resolves
+ need not be present in the namespace."
{:added "1.0"
:static true}
- [ns sym]
- (clojure.lang.Compiler/maybeResolveIn (the-ns ns) sym))
+ ([ns sym]
+ (ns-resolve ns nil sym))
+ ([ns env sym]
+ (when-not (contains? env sym)
+ (clojure.lang.Compiler/maybeResolveIn (the-ns ns) sym))))
(defn resolve
- "same as (ns-resolve *ns* symbol)"
+ "same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)"
{:added "1.0"
:static true}
- [sym] (ns-resolve *ns* sym))
+ ([sym] (ns-resolve *ns* sym))
+ ([env sym] (ns-resolve *ns* env sym)))
(defn array-map
"Constructs an array-map."
@@ -5635,7 +5639,7 @@
(add-doc-and-meta *out*
"A java.io.Writer object representing standard output for print operations.
- Defaults to System/out"
+ Defaults to System/out, wrapped in an OutputStreamWriter"
{:added "1.0"})
(add-doc-and-meta *err*
diff --git a/src/clj/clojure/main.clj b/src/clj/clojure/main.clj
index d52123fe..7aa74ab8 100644
--- a/src/clj/clojure/main.clj
+++ b/src/clj/clojure/main.clj
@@ -104,11 +104,11 @@
[e]
(let [ex (repl-exception e)
el (aget (.getStackTrace ex) 0)]
- (.println *err*
- (str (-> ex class .getSimpleName)
- " " (.getMessage ex) " "
- (when-not (instance? clojure.lang.Compiler$CompilerException ex)
- (str " " (stack-element-str el)))))))
+ (binding [*out* *err*]
+ (println (str (-> ex class .getSimpleName)
+ " " (.getMessage ex) " "
+ (when-not (instance? clojure.lang.Compiler$CompilerException ex)
+ (str " " (stack-element-str el))))))))
(defn repl
"Generic, reusable, read-eval-print loop. By default, reads from *in*,
@@ -248,6 +248,14 @@
(doseq [[opt arg] inits]
((init-dispatch opt) arg)))
+(defn- main-opt
+ "Call the -main function from a namespace with string arguments from
+ the command line."
+ [[_ main-ns & args] inits]
+ (with-bindings
+ (initialize args inits)
+ (apply (ns-resolve (doto (symbol main-ns) require) '-main) args)))
+
(defn- repl-opt
"Start a repl with args and inits. Print greeting if no eval options were
present"
@@ -284,6 +292,8 @@
(or
({"-r" repl-opt
"--repl" repl-opt
+ "-m" main-opt
+ "--main" main-opt
nil null-opt
"-h" help-opt
"--help" help-opt
@@ -316,14 +326,15 @@ java -cp clojure.jar clojure.main -i init.clj script.clj args...")
With no options or args, runs an interactive Read-Eval-Print Loop
init options:
- -i, --init path Load a file or resource
- -e, --eval string Evaluate expressions in string; print non-nil values
+ -i, --init path Load a file or resource
+ -e, --eval string Evaluate expressions in string; print non-nil values
main options:
- -r, --repl Run a repl
- path Run a script from from a file or resource
- - Run a script from standard input
- -h, -?, --help Print this help message and exit
+ -m, --main ns-name Call the -main function from a namespace with args
+ -r, --repl Run a repl
+ path Run a script from from a file or resource
+ - Run a script from standard input
+ -h, -?, --help Print this help message and exit
operation:
@@ -332,7 +343,7 @@ java -cp clojure.jar clojure.main -i init.clj script.clj args...")
- Binds *command-line-args* to a seq of strings containing command line
args that appear after any main option
- Runs all init options in order
- - Runs a repl or script if requested
+ - Calls a -main function or runs a repl or script if requested
The init options may be repeated and mixed freely, but must appear before
any main option. The appearance of any eval option before running a repl
diff --git a/src/clj/clojure/reflect.clj b/src/clj/clojure/reflect.clj
new file mode 100644
index 00000000..cf639568
--- /dev/null
+++ b/src/clj/clojure/reflect.clj
@@ -0,0 +1,123 @@
+; 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.
+
+(ns ^{:author "Stuart Halloway"
+ :added "1.3"
+ :doc "Reflection on Host Types
+Alpha - subject to change.
+
+Two main entry points:
+
+* type-reflect reflects on something that implements TypeReference.
+* reflect (for REPL use) reflects on the class of an instance, or
+ on a class if passed a class
+
+Key features:
+
+* Exposes the read side of reflection as pure data. Reflecting
+ on a type returns a map with keys :bases, :flags, and :members.
+
+* Canonicalizes class names as Clojure symbols. Types can extend
+ to the TypeReference protocol to indicate that they can be
+ unambiguously resolved as a type name. The canonical format
+ requires one non-Java-ish convention: array brackets are <>
+ instead of [] so they can be part of a Clojure symbol.
+
+* Pluggable Reflectors for different implementations. The default
+ JavaReflector is good when you have a class in hand, or use
+ the AsmReflector for \"hands off\" reflection without forcing
+ classes to load.
+
+Platform implementers must:
+
+* Create an implementation of Reflector.
+* Create one or more implementations of TypeReference.
+* def default-reflector to be an instance that satisfies Reflector."}
+ clojure.reflect
+ (:require [clojure.set :as set]))
+
+(defprotocol Reflector
+ "Protocol for reflection implementers."
+ (do-reflect [reflector typeref]))
+
+(defprotocol TypeReference
+ "A TypeReference can be unambiguously converted to a type name on
+ the host platform.
+
+ All typerefs are normalized into symbols. If you need to
+ normalize a typeref yourself, call typesym."
+ (typename [o] "Returns Java name as returned by ASM getClassName, e.g. byte[], java.lang.String[]"))
+
+(declare default-reflector)
+
+(defn type-reflect
+ "Alpha - subject to change.
+ Reflect on a typeref, returning a map with :bases, :flags, and
+ :members. In the discussion below, names are always Clojure symbols.
+
+ :bases a set of names of the type's bases
+ :flags a set of keywords naming the boolean attributes
+ of the type.
+ :members a set of the type's members. Each membrer is a map
+ and can be a constructor, method, or field.
+
+ Keys common to all members:
+ :name name of the type
+ :declaring-class name of the declarer
+ :flags keyword naming boolean attributes of the member
+
+ Keys specific to constructors:
+ :parameter-types vector of parameter type names
+ :exception-types vector of exception type names
+
+ Key specific to methods:
+ :parameter-types vector of parameter type names
+ :exception-types vector of exception type names
+ :return-type return type name
+
+ Keys specific to fields:
+ :type type name
+
+ Options:
+
+ :ancestors in addition to the keys described above, also
+ include an :ancestors key with the entire set of
+ ancestors, and add all ancestor members to
+ :members.
+ :reflector implementation to use. Defaults to JavaReflector,
+ AsmReflector is also an option."
+ {:added "1.3"}
+ [typeref & options]
+ (let [{:keys [ancestors reflector]}
+ (merge {:reflector default-reflector}
+ (apply hash-map options))
+ refl (partial do-reflect reflector)
+ result (refl typeref)]
+ ;; could make simpler loop of two args: names an
+ (if ancestors
+ (let [make-ancestor-map (fn [names]
+ (zipmap names (map refl names)))]
+ (loop [reflections (make-ancestor-map (:bases result))]
+ (let [ancestors-visited (set (keys reflections))
+ ancestors-to-visit (set/difference (set (mapcat :bases (vals reflections)))
+ ancestors-visited)]
+ (if (seq ancestors-to-visit)
+ (recur (merge reflections (make-ancestor-map ancestors-to-visit)))
+ (apply merge-with into result {:ancestors ancestors-visited}
+ (map #(select-keys % [:members]) (vals reflections)))))))
+ result)))
+
+(defn reflect
+ "Alpha - subject to change.
+ Reflect on the type of obj (or obj itself if obj is a class).
+ Return value and options are the same as for type-reflect. "
+ {:added "1.3"}
+ [obj & options]
+ (apply type-reflect (if (class? obj) obj (class obj)) options))
+
+(load "reflect/java")
diff --git a/src/clj/clojure/reflect/java.clj b/src/clj/clojure/reflect/java.clj
new file mode 100644
index 00000000..9a030899
--- /dev/null
+++ b/src/clj/clojure/reflect/java.clj
@@ -0,0 +1,253 @@
+; 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.
+
+;; Java-specific parts of clojure.reflect
+(in-ns 'clojure.reflect)
+
+(require '[clojure.set :as set]
+ '[clojure.string :as str])
+(import '[clojure.asm ClassReader ClassVisitor Type]
+ '[java.lang.reflect Modifier]
+ java.io.InputStream)
+
+(extend-protocol TypeReference
+ clojure.lang.Symbol
+ (typename [s] (str/replace (str s) "<>" "[]"))
+
+ Class
+ ;; neither .getName not .getSimpleName returns the right thing, so best to delegate to Type
+ (typename
+ [c]
+ (typename (Type/getType c)))
+
+ Type
+ (typename
+ [t]
+ (-> (.getClassName t))))
+
+(defn- typesym
+ "Given a typeref, create a legal Clojure symbol version of the
+ type's name."
+ [t]
+ (-> (typename t)
+ (str/replace "[]" "<>")
+ (symbol)))
+
+(defn- resource-name
+ "Given a typeref, return implied resource name. Used by Reflectors
+ such as ASM that need to find and read classbytes from files."
+ [typeref]
+ (-> (typename typeref)
+ (str/replace "." "/")
+ (str ".class")))
+
+(defn- access-flag
+ [[name flag & contexts]]
+ {:name name :flag flag :contexts (set (map keyword contexts))})
+
+(defn- field-descriptor->class-symbol
+ "Convert a Java field descriptor to a Clojure class symbol. Field
+ descriptors are described in section 4.3.2 of the JVM spec, 2nd ed.:
+ http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#14152"
+ [^String d]
+ {:pre [(string? d)]}
+ (typesym (Type/getType d)))
+
+(defn- internal-name->class-symbol
+ "Convert a Java internal name to a Clojure class symbol. Internal
+ names uses slashes instead of dots, e.g. java/lang/String. See
+ Section 4.2 of the JVM spec, 2nd ed.:
+
+ http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#14757"
+ [d]
+ {:pre [(string? d)]}
+ (typesym (Type/getObjectType d)))
+
+(def ^{:doc "The Java access bitflags, along with their friendly names and
+the kinds of objects to which they can apply."}
+ flag-descriptors
+ (vec
+ (map access-flag
+ [[:public 0x0001 :class :field :method]
+ [:private 0x002 :class :field :method]
+ [:protected 0x0004 :class :field :method]
+ [:static 0x0008 :field :method]
+ [:final 0x0010 :class :field :method]
+ ;; :super is ancient history and is unfindable (?) by
+ ;; reflection. skip it
+ #_[:super 0x0020 :class]
+ [:synchronized 0x0020 :method]
+ [:volatile 0x0040 :field]
+ [:bridge 0x0040 :method]
+ [:varargs 0x0080 :method]
+ [:transient 0x0080 :field]
+ [:native 0x0100 :method]
+ [:interface 0x0200 :class]
+ [:abstract 0x0400 :class :method]
+ [:strict 0x0800 :method]
+ [:synthetic 0x1000 :class :field :method]
+ [:annotation 0x2000 :class]
+ [:enum 0x4000 :class :field :inner]])))
+
+(defn- parse-flags
+ "Convert reflection bitflags into a set of keywords."
+ [flags context]
+ (reduce
+ (fn [result fd]
+ (if (and (get (:contexts fd) context)
+ (not (zero? (bit-and flags (:flag fd)))))
+ (conj result (:name fd))
+ result))
+ #{}
+ flag-descriptors))
+
+(defrecord Constructor
+ [name declaring-class parameter-types exception-types flags])
+
+(defn- constructor->map
+ [^java.lang.reflect.Constructor constructor]
+ (Constructor.
+ (symbol (.getName constructor))
+ (typesym (.getDeclaringClass constructor))
+ (vec (map typesym (.getParameterTypes constructor)))
+ (vec (map typesym (.getExceptionTypes constructor)))
+ (parse-flags (.getModifiers constructor) :method)))
+
+(defn- declared-constructors
+ "Return a set of the declared constructors of class as a Clojure map."
+ [^Class cls]
+ (set (map
+ constructor->map
+ (.getDeclaredConstructors cls))))
+
+(defrecord Method
+ [name return-type declaring-class parameter-types exception-types flags])
+
+(defn- method->map
+ [^java.lang.reflect.Method method]
+ (Method.
+ (symbol (.getName method))
+ (typesym (.getReturnType method))
+ (typesym (.getDeclaringClass method))
+ (vec (map typesym (.getParameterTypes method)))
+ (vec (map typesym (.getExceptionTypes method)))
+ (parse-flags (.getModifiers method) :method)))
+
+(defn- declared-methods
+ "Return a set of the declared constructors of class as a Clojure map."
+ [^Class cls]
+ (set (map
+ method->map
+ (.getDeclaredMethods cls))))
+
+(defrecord Field
+ [name type declaring-class flags])
+
+(defn- field->map
+ [^java.lang.reflect.Field field]
+ (Field.
+ (symbol (.getName field))
+ (typesym (.getType field))
+ (typesym (.getDeclaringClass field))
+ (parse-flags (.getModifiers field) :field)))
+
+(defn- declared-fields
+ "Return a set of the declared fields of class as a Clojure map."
+ [^Class cls]
+ (set (map
+ field->map
+ (.getDeclaredFields cls))))
+
+(deftype JavaReflector [classloader]
+ Reflector
+ (do-reflect [_ typeref]
+ (let [cls (Class/forName (typename typeref) false classloader)]
+ {:bases (not-empty (set (map typesym (bases cls))))
+ :flags (parse-flags (.getModifiers cls) :class)
+ :members (set/union (declared-fields cls)
+ (declared-methods cls)
+ (declared-constructors cls))})))
+
+(def ^:private default-reflector
+ (JavaReflector. (.getContextClassLoader (Thread/currentThread))))
+
+(defn- parse-method-descriptor
+ [^String md]
+ {:parameter-types (vec (map typesym (Type/getArgumentTypes md)))
+ :return-type (typesym (Type/getReturnType md))})
+
+(defprotocol ClassResolver
+ (^InputStream resolve-class [this name]
+ "Given a class name, return that typeref's class bytes as an InputStream."))
+
+(extend-protocol ClassResolver
+ clojure.lang.Fn
+ (resolve-class [this typeref] (this typeref))
+
+ ClassLoader
+ (resolve-class [this typeref]
+ (.getResourceAsStream this (resource-name typeref))))
+
+(deftype AsmReflector [class-resolver]
+ Reflector
+ (do-reflect [_ typeref]
+ (with-open [is (resolve-class class-resolver typeref)]
+ (let [class-symbol (typesym typeref)
+ r (ClassReader. is)
+ result (atom {:bases #{} :flags #{} :members #{}})]
+ (.accept
+ r
+ (reify
+ ClassVisitor
+ (visit [_ version access name signature superName interfaces]
+ (let [flags (parse-flags access :class)
+ ;; ignore java.lang.Object on interfaces to match reflection
+ superName (if (and (flags :interface)
+ (= superName "java/lang/Object"))
+ nil
+ superName)
+ bases (->> (cons superName interfaces)
+ (remove nil?)
+ (map internal-name->class-symbol)
+ (map symbol)
+ (set)
+ (not-empty))]
+ (swap! result merge {:bases bases
+ :flags flags})))
+ (visitSource [_ name debug])
+ (visitInnerClass [_ name outerName innerName access])
+ (visitField [_ access name desc signature value]
+ (swap! result update-in [:members] (fnil conj #{})
+ (Field. (symbol name)
+ (field-descriptor->class-symbol desc)
+ class-symbol
+ (parse-flags access :field)))
+ nil)
+ (visitMethod [_ access name desc signature exceptions]
+ (when-not (= name "<clinit>")
+ (let [constructor? (= name "<init>")]
+ (swap! result update-in [:members] (fnil conj #{})
+ (let [{:keys [parameter-types return-type]} (parse-method-descriptor desc)
+ flags (parse-flags access :method)]
+ (if constructor?
+ (Constructor. class-symbol
+ class-symbol
+ parameter-types
+ (vec (map internal-name->class-symbol exceptions))
+ flags)
+ (Method. (symbol name)
+ return-type
+ class-symbol
+ parameter-types
+ (vec (map internal-name->class-symbol exceptions))
+ flags))))))
+ nil)
+ (visitEnd [_])
+ ) 0)
+ @result))))
+
diff --git a/src/clj/clojure/repl.clj b/src/clj/clojure/repl.clj
index 2f50223d..77ef9dad 100644
--- a/src/clj/clojure/repl.clj
+++ b/src/clj/clojure/repl.clj
@@ -131,20 +131,23 @@ str-or-pattern."
most recent repl exception (*e), and a depth of 12."
{:added "1.3"}
([] (pst 12))
- ([depth]
- (when-let [e *e]
- (pst (root-cause e) depth)))
+ ([e-or-depth]
+ (if (instance? Throwable e-or-depth)
+ (pst e-or-depth 12)
+ (when-let [e *e]
+ (pst (root-cause e) e-or-depth))))
([^Throwable e depth]
- (.println *err* (str (-> e class .getSimpleName) " " (.getMessage e)))
- (let [st (.getStackTrace e)
- cause (.getCause e)]
- (doseq [el (take depth
- (remove #(#{"clojure.lang.RestFn" "clojure.lang.AFn"} (.getClassName %))
- st))]
- (.println *err* (str \tab (stack-element-str el))))
- (when cause
- (.println *err* "Caused by:")
- (pst cause (min depth
- (+ 2 (- (count (.getStackTrace cause))
- (count st)))))))))
+ (binding [*out* *err*]
+ (println (str (-> e class .getSimpleName) " " (.getMessage e)))
+ (let [st (.getStackTrace e)
+ cause (.getCause e)]
+ (doseq [el (take depth
+ (remove #(#{"clojure.lang.RestFn" "clojure.lang.AFn"} (.getClassName %))
+ st))]
+ (println (str \tab (stack-element-str el))))
+ (when cause
+ (println "Caused by:")
+ (pst cause (min depth
+ (+ 2 (- (count (.getStackTrace cause))
+ (count st))))))))))
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 24cb9359..b1b4d84e 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -34,51 +34,51 @@ import java.lang.reflect.Modifier;
public class Compiler implements Opcodes{
-static final Symbol DEF = Symbol.create("def");
-static final Symbol LOOP = Symbol.create("loop*");
-static final Symbol RECUR = Symbol.create("recur");
-static final Symbol IF = Symbol.create("if");
-static final Symbol LET = Symbol.create("let*");
-static final Symbol LETFN = Symbol.create("letfn*");
-static final Symbol DO = Symbol.create("do");
-static final Symbol FN = Symbol.create("fn*");
-static final Symbol QUOTE = Symbol.create("quote");
-static final Symbol THE_VAR = Symbol.create("var");
-static final Symbol DOT = Symbol.create(".");
-static final Symbol ASSIGN = Symbol.create("set!");
-//static final Symbol TRY_FINALLY = Symbol.create("try-finally");
-static final Symbol TRY = Symbol.create("try");
-static final Symbol CATCH = Symbol.create("catch");
-static final Symbol FINALLY = Symbol.create("finally");
-static final Symbol THROW = Symbol.create("throw");
-static final Symbol MONITOR_ENTER = Symbol.create("monitor-enter");
-static final Symbol MONITOR_EXIT = Symbol.create("monitor-exit");
-static final Symbol IMPORT = Symbol.create("clojure.core", "import*");
-//static final Symbol INSTANCE = Symbol.create("instance?");
-static final Symbol DEFTYPE = Symbol.create("deftype*");
-static final Symbol CASE = Symbol.create("case*");
-
-//static final Symbol THISFN = Symbol.create("thisfn");
-static final Symbol CLASS = Symbol.create("Class");
-static final Symbol NEW = Symbol.create("new");
-static final Symbol THIS = Symbol.create("this");
-static final Symbol REIFY = Symbol.create("reify*");
-//static final Symbol UNQUOTE = Symbol.create("unquote");
-//static final Symbol UNQUOTE_SPLICING = Symbol.create("unquote-splicing");
-//static final Symbol SYNTAX_QUOTE = Symbol.create("clojure.core", "syntax-quote");
-static final Symbol LIST = Symbol.create("clojure.core", "list");
-static final Symbol HASHMAP = Symbol.create("clojure.core", "hash-map");
-static final Symbol VECTOR = Symbol.create("clojure.core", "vector");
-static final Symbol IDENTITY = Symbol.create("clojure.core", "identity");
-
-static final Symbol _AMP_ = Symbol.create("&");
-static final Symbol ISEQ = Symbol.create("clojure.lang.ISeq");
+static final Symbol DEF = Symbol.intern("def");
+static final Symbol LOOP = Symbol.intern("loop*");
+static final Symbol RECUR = Symbol.intern("recur");
+static final Symbol IF = Symbol.intern("if");
+static final Symbol LET = Symbol.intern("let*");
+static final Symbol LETFN = Symbol.intern("letfn*");
+static final Symbol DO = Symbol.intern("do");
+static final Symbol FN = Symbol.intern("fn*");
+static final Symbol QUOTE = Symbol.intern("quote");
+static final Symbol THE_VAR = Symbol.intern("var");
+static final Symbol DOT = Symbol.intern(".");
+static final Symbol ASSIGN = Symbol.intern("set!");
+//static final Symbol TRY_FINALLY = Symbol.intern("try-finally");
+static final Symbol TRY = Symbol.intern("try");
+static final Symbol CATCH = Symbol.intern("catch");
+static final Symbol FINALLY = Symbol.intern("finally");
+static final Symbol THROW = Symbol.intern("throw");
+static final Symbol MONITOR_ENTER = Symbol.intern("monitor-enter");
+static final Symbol MONITOR_EXIT = Symbol.intern("monitor-exit");
+static final Symbol IMPORT = Symbol.intern("clojure.core", "import*");
+//static final Symbol INSTANCE = Symbol.intern("instance?");
+static final Symbol DEFTYPE = Symbol.intern("deftype*");
+static final Symbol CASE = Symbol.intern("case*");
+
+//static final Symbol THISFN = Symbol.intern("thisfn");
+static final Symbol CLASS = Symbol.intern("Class");
+static final Symbol NEW = Symbol.intern("new");
+static final Symbol THIS = Symbol.intern("this");
+static final Symbol REIFY = Symbol.intern("reify*");
+//static final Symbol UNQUOTE = Symbol.intern("unquote");
+//static final Symbol UNQUOTE_SPLICING = Symbol.intern("unquote-splicing");
+//static final Symbol SYNTAX_QUOTE = Symbol.intern("clojure.core", "syntax-quote");
+static final Symbol LIST = Symbol.intern("clojure.core", "list");
+static final Symbol HASHMAP = Symbol.intern("clojure.core", "hash-map");
+static final Symbol VECTOR = Symbol.intern("clojure.core", "vector");
+static final Symbol IDENTITY = Symbol.intern("clojure.core", "identity");
+
+static final Symbol _AMP_ = Symbol.intern("&");
+static final Symbol ISEQ = Symbol.intern("clojure.lang.ISeq");
static final Keyword inlineKey = Keyword.intern(null, "inline");
static final Keyword inlineAritiesKey = Keyword.intern(null, "inline-arities");
static final Keyword staticKey = Keyword.intern(null, "static");
static final Keyword arglistsKey = Keyword.intern(null, "arglists");
-static final Symbol INVOKE_STATIC = Symbol.create("invokeStatic");
+static final Symbol INVOKE_STATIC = Symbol.intern("invokeStatic");
static final Keyword volatileKey = Keyword.intern(null, "volatile");
static final Keyword implementsKey = Keyword.intern(null, "implements");
@@ -87,13 +87,13 @@ static final String COMPILE_STUB_PREFIX = "compile__stub";
static final Keyword protocolKey = Keyword.intern(null, "protocol");
static final Keyword onKey = Keyword.intern(null, "on");
-static final Symbol NS = Symbol.create("ns");
-static final Symbol IN_NS = Symbol.create("in-ns");
+static final Symbol NS = Symbol.intern("ns");
+static final Symbol IN_NS = Symbol.intern("in-ns");
-//static final Symbol IMPORT = Symbol.create("import");
-//static final Symbol USE = Symbol.create("use");
+//static final Symbol IMPORT = Symbol.intern("import");
+//static final Symbol USE = Symbol.intern("use");
-//static final Symbol IFN = Symbol.create("clojure.lang", "IFn");
+//static final Symbol IFN = Symbol.intern("clojure.lang", "IFn");
static final public IPersistentMap specials = PersistentHashMap.create(
DEF, new DefExpr.Parser(),
@@ -213,25 +213,25 @@ static final public Var IN_CATCH_FINALLY = Var.create(null);
static final public Var LOADER = Var.create();
//String
-static final public Var SOURCE = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")),
- Symbol.create("*source-path*"), "NO_SOURCE_FILE");
+static final public Var SOURCE = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")),
+ Symbol.intern("*source-path*"), "NO_SOURCE_FILE");
//String
-static final public Var SOURCE_PATH = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")),
- Symbol.create("*file*"), "NO_SOURCE_PATH");
+static final public Var SOURCE_PATH = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")),
+ Symbol.intern("*file*"), "NO_SOURCE_PATH");
//String
-static final public Var COMPILE_PATH = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")),
- Symbol.create("*compile-path*"), null);
+static final public Var COMPILE_PATH = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")),
+ Symbol.intern("*compile-path*"), null);
//boolean
-static final public Var COMPILE_FILES = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")),
- Symbol.create("*compile-files*"), Boolean.FALSE);
+static final public Var COMPILE_FILES = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")),
+ Symbol.intern("*compile-files*"), Boolean.FALSE);
-static final public Var INSTANCE = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")),
- Symbol.create("instance?"));
+static final public Var INSTANCE = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")),
+ Symbol.intern("instance?"));
-static final public Var ADD_ANNOTATIONS = Var.intern(Namespace.findOrCreate(Symbol.create("clojure.core")),
- Symbol.create("add-annotations"));
+static final public Var ADD_ANNOTATIONS = Var.intern(Namespace.findOrCreate(Symbol.intern("clojure.core")),
+ Symbol.intern("add-annotations"));
//Integer
static final public Var LINE = Var.create(0);
@@ -305,7 +305,7 @@ static Symbol resolveSymbol(Symbol sym){
Namespace ns = namespaceFor(sym);
if(ns == null || ns.name.name == sym.ns)
return sym;
- return Symbol.create(ns.name.name, sym.name);
+ return Symbol.intern(ns.name.name, sym.name);
}
Object o = currentNS().getMapping(sym);
if(o == null)
@@ -315,7 +315,7 @@ static Symbol resolveSymbol(Symbol sym){
else if(o instanceof Var)
{
Var v = (Var) o;
- return Symbol.create(v.ns.name.name, v.sym.name);
+ return Symbol.intern(v.ns.name.name, v.sym.name);
}
return null;
@@ -331,7 +331,7 @@ static class DefExpr implements Expr{
final static Method bindRootMethod = Method.getMethod("void bindRoot(Object)");
final static Method setTagMethod = Method.getMethod("void setTag(clojure.lang.Symbol)");
final static Method setMetaMethod = Method.getMethod("void setMeta(clojure.lang.IPersistentMap)");
- final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String, String)");
+ final static Method symintern = Method.getMethod("clojure.lang.Symbol intern(String, String)");
public DefExpr(String source, int line, Var var, Expr init, Expr meta, boolean initProvided){
this.source = source;
@@ -3610,7 +3610,7 @@ static public class ObjExpr implements Expr{
}
final static Method kwintern = Method.getMethod("clojure.lang.Keyword intern(String, String)");
- final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String)");
+ final static Method symintern = Method.getMethod("clojure.lang.Symbol intern(String)");
final static Method varintern =
Method.getMethod("clojure.lang.Var intern(clojure.lang.Symbol, clojure.lang.Symbol)");
@@ -4093,7 +4093,7 @@ static public class ObjExpr implements Expr{
gen.push(((Symbol) value).ns);
gen.push(((Symbol) value).name);
gen.invokeStatic(Type.getType(Symbol.class),
- Method.getMethod("clojure.lang.Symbol create(String,String)"));
+ Method.getMethod("clojure.lang.Symbol intern(String,String)"));
}
else if(value instanceof Keyword)
{
@@ -6148,7 +6148,7 @@ private static Expr analyzeSymbol(Symbol sym) throws Exception{
{
if(namespaceFor(sym) == null)
{
- Symbol nsSym = Symbol.create(sym.ns);
+ Symbol nsSym = Symbol.intern(sym.ns);
Class c = HostExpr.maybeClass(nsSym, false);
if(c != null)
{
@@ -6209,7 +6209,7 @@ static Namespace namespaceFor(Symbol sym){
static Namespace namespaceFor(Namespace inns, Symbol sym){
//note, presumes non-nil sym.ns
// first check against currentNS' aliases...
- Symbol nsSym = Symbol.create(sym.ns);
+ Symbol nsSym = Symbol.intern(sym.ns);
Namespace ns = inns.lookupAlias(nsSym);
if(ns == null)
{
@@ -6227,7 +6227,7 @@ static public Object resolveIn(Namespace n, Symbol sym, boolean allowPrivate) th
if(ns == null)
throw new Exception("No such namespace: " + sym.ns);
- Var v = ns.findInternedVar(Symbol.create(sym.name));
+ Var v = ns.findInternedVar(Symbol.intern(sym.name));
if(v == null)
throw new Exception("No such var: " + sym);
else if(v.ns != currentNS() && !v.isPublic() && !allowPrivate)
@@ -6270,7 +6270,7 @@ static public Object maybeResolveIn(Namespace n, Symbol sym) throws Exception{
Namespace ns = namespaceFor(n, sym);
if(ns == null)
return null;
- Var v = ns.findInternedVar(Symbol.create(sym.name));
+ Var v = ns.findInternedVar(Symbol.intern(sym.name));
if(v == null)
return null;
return v;
@@ -6302,7 +6302,7 @@ static Var lookupVar(Symbol sym, boolean internNew) throws Exception{
if(ns == null)
return null;
//throw new Exception("No such namespace: " + sym.ns);
- Symbol name = Symbol.create(sym.name);
+ Symbol name = Symbol.intern(sym.name);
if(internNew && ns == currentNS())
var = currentNS().intern(name);
else
@@ -6320,7 +6320,7 @@ static Var lookupVar(Symbol sym, boolean internNew) throws Exception{
{
//introduce a new var in the current ns
if(internNew)
- var = currentNS().intern(Symbol.create(sym.name));
+ var = currentNS().intern(Symbol.intern(sym.name));
}
else if(o instanceof Var)
{
@@ -6478,8 +6478,8 @@ static public void writeClassFile(String internalName, byte[] bytecode) throws E
}
public static void pushNS(){
- Var.pushThreadBindings(PersistentHashMap.create(Var.intern(Symbol.create("clojure.core"),
- Symbol.create("*ns*")), null));
+ Var.pushThreadBindings(PersistentHashMap.create(Var.intern(Symbol.intern("clojure.core"),
+ Symbol.intern("*ns*")), null));
}
public static ILookupThunk getLookupThunk(Object target, Keyword k){
@@ -7124,7 +7124,7 @@ public static class NewInstanceMethod extends ObjMethod{
if(tag != null)
hinted = true;
if(p.getNamespace() != null)
- p = Symbol.create(p.name);
+ p = Symbol.intern(p.name);
Class pclass = tagClass(tag);
pclasses[i] = pclass;
psyms[i] = p;
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java
index 91a854e7..35addd7c 100644
--- a/src/jvm/clojure/lang/LispReader.java
+++ b/src/jvm/clojure/lang/LispReader.java
@@ -22,22 +22,22 @@ import java.lang.*;
public class LispReader{
-static final Symbol QUOTE = Symbol.create("quote");
-static final Symbol THE_VAR = Symbol.create("var");
-//static Symbol SYNTAX_QUOTE = Symbol.create(null, "syntax-quote");
-static Symbol UNQUOTE = Symbol.create("clojure.core", "unquote");
-static Symbol UNQUOTE_SPLICING = Symbol.create("clojure.core", "unquote-splicing");
-static Symbol CONCAT = Symbol.create("clojure.core", "concat");
-static Symbol SEQ = Symbol.create("clojure.core", "seq");
-static Symbol LIST = Symbol.create("clojure.core", "list");
-static Symbol APPLY = Symbol.create("clojure.core", "apply");
-static Symbol HASHMAP = Symbol.create("clojure.core", "hash-map");
-static Symbol HASHSET = Symbol.create("clojure.core", "hash-set");
-static Symbol VECTOR = Symbol.create("clojure.core", "vector");
-static Symbol WITH_META = Symbol.create("clojure.core", "with-meta");
-static Symbol META = Symbol.create("clojure.core", "meta");
-static Symbol DEREF = Symbol.create("clojure.core", "deref");
-//static Symbol DEREF_BANG = Symbol.create("clojure.core", "deref!");
+static final Symbol QUOTE = Symbol.intern("quote");
+static final Symbol THE_VAR = Symbol.intern("var");
+//static Symbol SYNTAX_QUOTE = Symbol.intern(null, "syntax-quote");
+static Symbol UNQUOTE = Symbol.intern("clojure.core", "unquote");
+static Symbol UNQUOTE_SPLICING = Symbol.intern("clojure.core", "unquote-splicing");
+static Symbol CONCAT = Symbol.intern("clojure.core", "concat");
+static Symbol SEQ = Symbol.intern("clojure.core", "seq");
+static Symbol LIST = Symbol.intern("clojure.core", "list");
+static Symbol APPLY = Symbol.intern("clojure.core", "apply");
+static Symbol HASHMAP = Symbol.intern("clojure.core", "hash-map");
+static Symbol HASHSET = Symbol.intern("clojure.core", "hash-set");
+static Symbol VECTOR = Symbol.intern("clojure.core", "vector");
+static Symbol WITH_META = Symbol.intern("clojure.core", "with-meta");
+static Symbol META = Symbol.intern("clojure.core", "meta");
+static Symbol DEREF = Symbol.intern("clojure.core", "deref");
+//static Symbol DEREF_BANG = Symbol.intern("clojure.core", "deref!");
static IFn[] macros = new IFn[256];
static IFn[] dispatchMacros = new IFn[256];
@@ -50,8 +50,8 @@ static Pattern intPat =
"([-+]?)(?:(0)|([1-9][0-9]*)|0[xX]([0-9A-Fa-f]+)|0([0-7]+)|([1-9][0-9]?)[rR]([0-9A-Za-z]+)|0[0-9]+)(N)?");
static Pattern ratioPat = Pattern.compile("([-+]?[0-9]+)/([0-9]+)");
static Pattern floatPat = Pattern.compile("([-+]?[0-9]+(\\.[0-9]*)?([eE][-+]?[0-9]+)?)(M)?");
-static final Symbol SLASH = Symbol.create("/");
-static final Symbol CLOJURE_SLASH = Symbol.create("clojure.core","/");
+static final Symbol SLASH = Symbol.intern("/");
+static final Symbol CLOJURE_SLASH = Symbol.intern("clojure.core","/");
//static Pattern accessorPat = Pattern.compile("\\.[a-zA-Z_]\\w*");
//static Pattern instanceMemberPat = Pattern.compile("\\.([a-zA-Z_][\\w\\.]*)\\.([a-zA-Z_]\\w*)");
//static Pattern staticMemberPat = Pattern.compile("([a-zA-Z_][\\w\\.]*)\\.([a-zA-Z_]\\w*)");
@@ -929,7 +929,7 @@ public static class ListReader extends AFn{
}
static class CtorReader extends AFn{
- static final Symbol cls = Symbol.create("class");
+ static final Symbol cls = Symbol.intern("class");
public Object invoke(Object reader, Object leftangle) throws Exception{
PushbackReader r = (PushbackReader) reader;
diff --git a/src/jvm/clojure/lang/PersistentQueue.java b/src/jvm/clojure/lang/PersistentQueue.java
index fb7781c3..674fd790 100644
--- a/src/jvm/clojure/lang/PersistentQueue.java
+++ b/src/jvm/clojure/lang/PersistentQueue.java
@@ -17,22 +17,24 @@ import java.util.Iterator;
/**
* conses onto rear, peeks/pops from front
* See Okasaki's Batched Queues
- * This differs in that it uses a PersistentArrayList as the rear, which is in-order,
+ * This differs in that it uses a PersistentVector as the rear, which is in-order,
* so no reversing or suspensions required for persistent use
*/
-public class PersistentQueue extends Obj implements IPersistentList, Collection{
+public class PersistentQueue extends Obj implements IPersistentList, Collection, Counted{
-final public static PersistentQueue EMPTY = new PersistentQueue(null, null, null);
+final public static PersistentQueue EMPTY = new PersistentQueue(null, 0, null, null);
//*
+final int cnt;
final ISeq f;
final PersistentVector r;
//static final int INITIAL_REAR_SIZE = 4;
int _hash = -1;
-PersistentQueue(IPersistentMap meta, ISeq f, PersistentVector r){
+PersistentQueue(IPersistentMap meta, int cnt, ISeq f, PersistentVector r){
super(meta);
+ this.cnt = cnt;
this.f = f;
this.r = r;
}
@@ -93,11 +95,11 @@ public PersistentQueue pop(){
f1 = RT.seq(r);
r1 = null;
}
- return new PersistentQueue(meta(), f1, r1);
+ return new PersistentQueue(meta(), cnt - 1, f1, r1);
}
public int count(){
- return RT.count(f) + RT.count(r);
+ return cnt;
}
public ISeq seq(){
@@ -108,17 +110,17 @@ public ISeq seq(){
public PersistentQueue cons(Object o){
if(f == null) //empty
- return new PersistentQueue(meta(), RT.list(o), null);
+ return new PersistentQueue(meta(), cnt + 1, RT.list(o), null);
else
- return new PersistentQueue(meta(), f, (r != null ? r : PersistentVector.EMPTY).cons(o));
+ return new PersistentQueue(meta(), cnt + 1, f, (r != null ? r : PersistentVector.EMPTY).cons(o));
}
public IPersistentCollection empty(){
- return EMPTY.withMeta(meta());
+ return EMPTY.withMeta(meta());
}
public PersistentQueue withMeta(IPersistentMap meta){
- return new PersistentQueue(meta, f, r);
+ return new PersistentQueue(meta, cnt, f, r);
}
static class Seq extends ASeq{
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java
index c0d3e4ce..97abd85a 100644
--- a/src/jvm/clojure/lang/RT.java
+++ b/src/jvm/clojure/lang/RT.java
@@ -29,189 +29,189 @@ import java.nio.charset.Charset;
public class RT{
-static final public Boolean T = Boolean.TRUE;//Keyword.intern(Symbol.create(null, "t"));
-static final public Boolean F = Boolean.FALSE;//Keyword.intern(Symbol.create(null, "t"));
+static final public Boolean T = Boolean.TRUE;//Keyword.intern(Symbol.intern(null, "t"));
+static final public Boolean F = Boolean.FALSE;//Keyword.intern(Symbol.intern(null, "t"));
static final public String LOADER_SUFFIX = "__init";
//simple-symbol->class
final static IPersistentMap DEFAULT_IMPORTS = map(
-// Symbol.create("RT"), "clojure.lang.RT",
-// Symbol.create("Num"), "clojure.lang.Num",
-// Symbol.create("Symbol"), "clojure.lang.Symbol",
-// Symbol.create("Keyword"), "clojure.lang.Keyword",
-// Symbol.create("Var"), "clojure.lang.Var",
-// Symbol.create("Ref"), "clojure.lang.Ref",
-// Symbol.create("IFn"), "clojure.lang.IFn",
-// Symbol.create("IObj"), "clojure.lang.IObj",
-// Symbol.create("ISeq"), "clojure.lang.ISeq",
-// Symbol.create("IPersistentCollection"),
+// Symbol.intern("RT"), "clojure.lang.RT",
+// Symbol.intern("Num"), "clojure.lang.Num",
+// Symbol.intern("Symbol"), "clojure.lang.Symbol",
+// Symbol.intern("Keyword"), "clojure.lang.Keyword",
+// Symbol.intern("Var"), "clojure.lang.Var",
+// Symbol.intern("Ref"), "clojure.lang.Ref",
+// Symbol.intern("IFn"), "clojure.lang.IFn",
+// Symbol.intern("IObj"), "clojure.lang.IObj",
+// Symbol.intern("ISeq"), "clojure.lang.ISeq",
+// Symbol.intern("IPersistentCollection"),
// "clojure.lang.IPersistentCollection",
-// Symbol.create("IPersistentMap"), "clojure.lang.IPersistentMap",
-// Symbol.create("IPersistentList"), "clojure.lang.IPersistentList",
-// Symbol.create("IPersistentVector"), "clojure.lang.IPersistentVector",
-Symbol.create("Boolean"), Boolean.class,
-Symbol.create("Byte"), Byte.class,
-Symbol.create("Character"), Character.class,
-Symbol.create("Class"), Class.class,
-Symbol.create("ClassLoader"), ClassLoader.class,
-Symbol.create("Compiler"), Compiler.class,
-Symbol.create("Double"), Double.class,
-Symbol.create("Enum"), Enum.class,
-Symbol.create("Float"), Float.class,
-Symbol.create("InheritableThreadLocal"), InheritableThreadLocal.class,
-Symbol.create("Integer"), Integer.class,
-Symbol.create("Long"), Long.class,
-Symbol.create("Math"), Math.class,
-Symbol.create("Number"), Number.class,
-Symbol.create("Object"), Object.class,
-Symbol.create("Package"), Package.class,
-Symbol.create("Process"), Process.class,
-Symbol.create("ProcessBuilder"), ProcessBuilder.class,
-Symbol.create("Runtime"), Runtime.class,
-Symbol.create("RuntimePermission"), RuntimePermission.class,
-Symbol.create("SecurityManager"), SecurityManager.class,
-Symbol.create("Short"), Short.class,
-Symbol.create("StackTraceElement"), StackTraceElement.class,
-Symbol.create("StrictMath"), StrictMath.class,
-Symbol.create("String"), String.class,
-Symbol.create("StringBuffer"), StringBuffer.class,
-Symbol.create("StringBuilder"), StringBuilder.class,
-Symbol.create("System"), System.class,
-Symbol.create("Thread"), Thread.class,
-Symbol.create("ThreadGroup"), ThreadGroup.class,
-Symbol.create("ThreadLocal"), ThreadLocal.class,
-Symbol.create("Throwable"), Throwable.class,
-Symbol.create("Void"), Void.class,
-Symbol.create("Appendable"), Appendable.class,
-Symbol.create("CharSequence"), CharSequence.class,
-Symbol.create("Cloneable"), Cloneable.class,
-Symbol.create("Comparable"), Comparable.class,
-Symbol.create("Iterable"), Iterable.class,
-Symbol.create("Readable"), Readable.class,
-Symbol.create("Runnable"), Runnable.class,
-Symbol.create("Callable"), Callable.class,
-Symbol.create("BigInteger"), BigInteger.class,
-Symbol.create("BigDecimal"), BigDecimal.class,
-Symbol.create("ArithmeticException"), ArithmeticException.class,
-Symbol.create("ArrayIndexOutOfBoundsException"), ArrayIndexOutOfBoundsException.class,
-Symbol.create("ArrayStoreException"), ArrayStoreException.class,
-Symbol.create("ClassCastException"), ClassCastException.class,
-Symbol.create("ClassNotFoundException"), ClassNotFoundException.class,
-Symbol.create("CloneNotSupportedException"), CloneNotSupportedException.class,
-Symbol.create("EnumConstantNotPresentException"), EnumConstantNotPresentException.class,
-Symbol.create("Exception"), Exception.class,
-Symbol.create("IllegalAccessException"), IllegalAccessException.class,
-Symbol.create("IllegalArgumentException"), IllegalArgumentException.class,
-Symbol.create("IllegalMonitorStateException"), IllegalMonitorStateException.class,
-Symbol.create("IllegalStateException"), IllegalStateException.class,
-Symbol.create("IllegalThreadStateException"), IllegalThreadStateException.class,
-Symbol.create("IndexOutOfBoundsException"), IndexOutOfBoundsException.class,
-Symbol.create("InstantiationException"), InstantiationException.class,
-Symbol.create("InterruptedException"), InterruptedException.class,
-Symbol.create("NegativeArraySizeException"), NegativeArraySizeException.class,
-Symbol.create("NoSuchFieldException"), NoSuchFieldException.class,
-Symbol.create("NoSuchMethodException"), NoSuchMethodException.class,
-Symbol.create("NullPointerException"), NullPointerException.class,
-Symbol.create("NumberFormatException"), NumberFormatException.class,
-Symbol.create("RuntimeException"), RuntimeException.class,
-Symbol.create("SecurityException"), SecurityException.class,
-Symbol.create("StringIndexOutOfBoundsException"), StringIndexOutOfBoundsException.class,
-Symbol.create("TypeNotPresentException"), TypeNotPresentException.class,
-Symbol.create("UnsupportedOperationException"), UnsupportedOperationException.class,
-Symbol.create("AbstractMethodError"), AbstractMethodError.class,
-Symbol.create("AssertionError"), AssertionError.class,
-Symbol.create("ClassCircularityError"), ClassCircularityError.class,
-Symbol.create("ClassFormatError"), ClassFormatError.class,
-Symbol.create("Error"), Error.class,
-Symbol.create("ExceptionInInitializerError"), ExceptionInInitializerError.class,
-Symbol.create("IllegalAccessError"), IllegalAccessError.class,
-Symbol.create("IncompatibleClassChangeError"), IncompatibleClassChangeError.class,
-Symbol.create("InstantiationError"), InstantiationError.class,
-Symbol.create("InternalError"), InternalError.class,
-Symbol.create("LinkageError"), LinkageError.class,
-Symbol.create("NoClassDefFoundError"), NoClassDefFoundError.class,
-Symbol.create("NoSuchFieldError"), NoSuchFieldError.class,
-Symbol.create("NoSuchMethodError"), NoSuchMethodError.class,
-Symbol.create("OutOfMemoryError"), OutOfMemoryError.class,
-Symbol.create("StackOverflowError"), StackOverflowError.class,
-Symbol.create("ThreadDeath"), ThreadDeath.class,
-Symbol.create("UnknownError"), UnknownError.class,
-Symbol.create("UnsatisfiedLinkError"), UnsatisfiedLinkError.class,
-Symbol.create("UnsupportedClassVersionError"), UnsupportedClassVersionError.class,
-Symbol.create("VerifyError"), VerifyError.class,
-Symbol.create("VirtualMachineError"), VirtualMachineError.class,
-Symbol.create("Thread$UncaughtExceptionHandler"), Thread.UncaughtExceptionHandler.class,
-Symbol.create("Thread$State"), Thread.State.class,
-Symbol.create("Deprecated"), Deprecated.class,
-Symbol.create("Override"), Override.class,
-Symbol.create("SuppressWarnings"), SuppressWarnings.class
-
-// Symbol.create("Collection"), "java.util.Collection",
-// Symbol.create("Comparator"), "java.util.Comparator",
-// Symbol.create("Enumeration"), "java.util.Enumeration",
-// Symbol.create("EventListener"), "java.util.EventListener",
-// Symbol.create("Formattable"), "java.util.Formattable",
-// Symbol.create("Iterator"), "java.util.Iterator",
-// Symbol.create("List"), "java.util.List",
-// Symbol.create("ListIterator"), "java.util.ListIterator",
-// Symbol.create("Map"), "java.util.Map",
-// Symbol.create("Map$Entry"), "java.util.Map$Entry",
-// Symbol.create("Observer"), "java.util.Observer",
-// Symbol.create("Queue"), "java.util.Queue",
-// Symbol.create("RandomAccess"), "java.util.RandomAccess",
-// Symbol.create("Set"), "java.util.Set",
-// Symbol.create("SortedMap"), "java.util.SortedMap",
-// Symbol.create("SortedSet"), "java.util.SortedSet"
+// Symbol.intern("IPersistentMap"), "clojure.lang.IPersistentMap",
+// Symbol.intern("IPersistentList"), "clojure.lang.IPersistentList",
+// Symbol.intern("IPersistentVector"), "clojure.lang.IPersistentVector",
+Symbol.intern("Boolean"), Boolean.class,
+Symbol.intern("Byte"), Byte.class,
+Symbol.intern("Character"), Character.class,
+Symbol.intern("Class"), Class.class,
+Symbol.intern("ClassLoader"), ClassLoader.class,
+Symbol.intern("Compiler"), Compiler.class,
+Symbol.intern("Double"), Double.class,
+Symbol.intern("Enum"), Enum.class,
+Symbol.intern("Float"), Float.class,
+Symbol.intern("InheritableThreadLocal"), InheritableThreadLocal.class,
+Symbol.intern("Integer"), Integer.class,
+Symbol.intern("Long"), Long.class,
+Symbol.intern("Math"), Math.class,
+Symbol.intern("Number"), Number.class,
+Symbol.intern("Object"), Object.class,
+Symbol.intern("Package"), Package.class,
+Symbol.intern("Process"), Process.class,
+Symbol.intern("ProcessBuilder"), ProcessBuilder.class,
+Symbol.intern("Runtime"), Runtime.class,
+Symbol.intern("RuntimePermission"), RuntimePermission.class,
+Symbol.intern("SecurityManager"), SecurityManager.class,
+Symbol.intern("Short"), Short.class,
+Symbol.intern("StackTraceElement"), StackTraceElement.class,
+Symbol.intern("StrictMath"), StrictMath.class,
+Symbol.intern("String"), String.class,
+Symbol.intern("StringBuffer"), StringBuffer.class,
+Symbol.intern("StringBuilder"), StringBuilder.class,
+Symbol.intern("System"), System.class,
+Symbol.intern("Thread"), Thread.class,
+Symbol.intern("ThreadGroup"), ThreadGroup.class,
+Symbol.intern("ThreadLocal"), ThreadLocal.class,
+Symbol.intern("Throwable"), Throwable.class,
+Symbol.intern("Void"), Void.class,
+Symbol.intern("Appendable"), Appendable.class,
+Symbol.intern("CharSequence"), CharSequence.class,
+Symbol.intern("Cloneable"), Cloneable.class,
+Symbol.intern("Comparable"), Comparable.class,
+Symbol.intern("Iterable"), Iterable.class,
+Symbol.intern("Readable"), Readable.class,
+Symbol.intern("Runnable"), Runnable.class,
+Symbol.intern("Callable"), Callable.class,
+Symbol.intern("BigInteger"), BigInteger.class,
+Symbol.intern("BigDecimal"), BigDecimal.class,
+Symbol.intern("ArithmeticException"), ArithmeticException.class,
+Symbol.intern("ArrayIndexOutOfBoundsException"), ArrayIndexOutOfBoundsException.class,
+Symbol.intern("ArrayStoreException"), ArrayStoreException.class,
+Symbol.intern("ClassCastException"), ClassCastException.class,
+Symbol.intern("ClassNotFoundException"), ClassNotFoundException.class,
+Symbol.intern("CloneNotSupportedException"), CloneNotSupportedException.class,
+Symbol.intern("EnumConstantNotPresentException"), EnumConstantNotPresentException.class,
+Symbol.intern("Exception"), Exception.class,
+Symbol.intern("IllegalAccessException"), IllegalAccessException.class,
+Symbol.intern("IllegalArgumentException"), IllegalArgumentException.class,
+Symbol.intern("IllegalMonitorStateException"), IllegalMonitorStateException.class,
+Symbol.intern("IllegalStateException"), IllegalStateException.class,
+Symbol.intern("IllegalThreadStateException"), IllegalThreadStateException.class,
+Symbol.intern("IndexOutOfBoundsException"), IndexOutOfBoundsException.class,
+Symbol.intern("InstantiationException"), InstantiationException.class,
+Symbol.intern("InterruptedException"), InterruptedException.class,
+Symbol.intern("NegativeArraySizeException"), NegativeArraySizeException.class,
+Symbol.intern("NoSuchFieldException"), NoSuchFieldException.class,
+Symbol.intern("NoSuchMethodException"), NoSuchMethodException.class,
+Symbol.intern("NullPointerException"), NullPointerException.class,
+Symbol.intern("NumberFormatException"), NumberFormatException.class,
+Symbol.intern("RuntimeException"), RuntimeException.class,
+Symbol.intern("SecurityException"), SecurityException.class,
+Symbol.intern("StringIndexOutOfBoundsException"), StringIndexOutOfBoundsException.class,
+Symbol.intern("TypeNotPresentException"), TypeNotPresentException.class,
+Symbol.intern("UnsupportedOperationException"), UnsupportedOperationException.class,
+Symbol.intern("AbstractMethodError"), AbstractMethodError.class,
+Symbol.intern("AssertionError"), AssertionError.class,
+Symbol.intern("ClassCircularityError"), ClassCircularityError.class,
+Symbol.intern("ClassFormatError"), ClassFormatError.class,
+Symbol.intern("Error"), Error.class,
+Symbol.intern("ExceptionInInitializerError"), ExceptionInInitializerError.class,
+Symbol.intern("IllegalAccessError"), IllegalAccessError.class,
+Symbol.intern("IncompatibleClassChangeError"), IncompatibleClassChangeError.class,
+Symbol.intern("InstantiationError"), InstantiationError.class,
+Symbol.intern("InternalError"), InternalError.class,
+Symbol.intern("LinkageError"), LinkageError.class,
+Symbol.intern("NoClassDefFoundError"), NoClassDefFoundError.class,
+Symbol.intern("NoSuchFieldError"), NoSuchFieldError.class,
+Symbol.intern("NoSuchMethodError"), NoSuchMethodError.class,
+Symbol.intern("OutOfMemoryError"), OutOfMemoryError.class,
+Symbol.intern("StackOverflowError"), StackOverflowError.class,
+Symbol.intern("ThreadDeath"), ThreadDeath.class,
+Symbol.intern("UnknownError"), UnknownError.class,
+Symbol.intern("UnsatisfiedLinkError"), UnsatisfiedLinkError.class,
+Symbol.intern("UnsupportedClassVersionError"), UnsupportedClassVersionError.class,
+Symbol.intern("VerifyError"), VerifyError.class,
+Symbol.intern("VirtualMachineError"), VirtualMachineError.class,
+Symbol.intern("Thread$UncaughtExceptionHandler"), Thread.UncaughtExceptionHandler.class,
+Symbol.intern("Thread$State"), Thread.State.class,
+Symbol.intern("Deprecated"), Deprecated.class,
+Symbol.intern("Override"), Override.class,
+Symbol.intern("SuppressWarnings"), SuppressWarnings.class
+
+// Symbol.intern("Collection"), "java.util.Collection",
+// Symbol.intern("Comparator"), "java.util.Comparator",
+// Symbol.intern("Enumeration"), "java.util.Enumeration",
+// Symbol.intern("EventListener"), "java.util.EventListener",
+// Symbol.intern("Formattable"), "java.util.Formattable",
+// Symbol.intern("Iterator"), "java.util.Iterator",
+// Symbol.intern("List"), "java.util.List",
+// Symbol.intern("ListIterator"), "java.util.ListIterator",
+// Symbol.intern("Map"), "java.util.Map",
+// Symbol.intern("Map$Entry"), "java.util.Map$Entry",
+// Symbol.intern("Observer"), "java.util.Observer",
+// Symbol.intern("Queue"), "java.util.Queue",
+// Symbol.intern("RandomAccess"), "java.util.RandomAccess",
+// Symbol.intern("Set"), "java.util.Set",
+// Symbol.intern("SortedMap"), "java.util.SortedMap",
+// Symbol.intern("SortedSet"), "java.util.SortedSet"
);
// single instance of UTF-8 Charset, so as to avoid catching UnsupportedCharsetExceptions everywhere
static public Charset UTF8 = Charset.forName("UTF-8");
-static public final Namespace CLOJURE_NS = Namespace.findOrCreate(Symbol.create("clojure.core"));
-//static final Namespace USER_NS = Namespace.findOrCreate(Symbol.create("user"));
+static public final Namespace CLOJURE_NS = Namespace.findOrCreate(Symbol.intern("clojure.core"));
+//static final Namespace USER_NS = Namespace.findOrCreate(Symbol.intern("user"));
final static public Var OUT =
- Var.intern(CLOJURE_NS, Symbol.create("*out*"), new OutputStreamWriter(System.out));
+ Var.intern(CLOJURE_NS, Symbol.intern("*out*"), new OutputStreamWriter(System.out));
final static public Var IN =
- Var.intern(CLOJURE_NS, Symbol.create("*in*"),
+ Var.intern(CLOJURE_NS, Symbol.intern("*in*"),
new LineNumberingPushbackReader(new InputStreamReader(System.in)));
final static public Var ERR =
- Var.intern(CLOJURE_NS, Symbol.create("*err*"),
+ Var.intern(CLOJURE_NS, Symbol.intern("*err*"),
new PrintWriter(new OutputStreamWriter(System.err), true));
final static Keyword TAG_KEY = Keyword.intern(null, "tag");
-final static public Var AGENT = Var.intern(CLOJURE_NS, Symbol.create("*agent*"), null);
-final static public Var READEVAL = Var.intern(CLOJURE_NS, Symbol.create("*read-eval*"), T);
-final static public Var ASSERT = Var.intern(CLOJURE_NS, Symbol.create("*assert*"), T);
-final static public Var MATH_CONTEXT = Var.intern(CLOJURE_NS, Symbol.create("*math-context*"), null);
+final static public Var AGENT = Var.intern(CLOJURE_NS, Symbol.intern("*agent*"), null);
+final static public Var READEVAL = Var.intern(CLOJURE_NS, Symbol.intern("*read-eval*"), T);
+final static public Var ASSERT = Var.intern(CLOJURE_NS, Symbol.intern("*assert*"), T);
+final static public Var MATH_CONTEXT = Var.intern(CLOJURE_NS, Symbol.intern("*math-context*"), null);
static Keyword LINE_KEY = Keyword.intern(null, "line");
static Keyword FILE_KEY = Keyword.intern(null, "file");
static Keyword DECLARED_KEY = Keyword.intern(null, "declared");
static Keyword DOC_KEY = Keyword.intern(null, "doc");
final static public Var USE_CONTEXT_CLASSLOADER =
- Var.intern(CLOJURE_NS, Symbol.create("*use-context-classloader*"), T);
-//final static public Var CURRENT_MODULE = Var.intern(Symbol.create("clojure.core", "current-module"),
+ Var.intern(CLOJURE_NS, Symbol.intern("*use-context-classloader*"), T);
+//final static public Var CURRENT_MODULE = Var.intern(Symbol.intern("clojure.core", "current-module"),
// Module.findOrCreateModule("clojure/user"));
-final static Symbol LOAD_FILE = Symbol.create("load-file");
-final static Symbol IN_NAMESPACE = Symbol.create("in-ns");
-final static Symbol NAMESPACE = Symbol.create("ns");
-static final Symbol IDENTICAL = Symbol.create("identical?");
-final static Var CMD_LINE_ARGS = Var.intern(CLOJURE_NS, Symbol.create("*command-line-args*"), null);
+final static Symbol LOAD_FILE = Symbol.intern("load-file");
+final static Symbol IN_NAMESPACE = Symbol.intern("in-ns");
+final static Symbol NAMESPACE = Symbol.intern("ns");
+static final Symbol IDENTICAL = Symbol.intern("identical?");
+final static Var CMD_LINE_ARGS = Var.intern(CLOJURE_NS, Symbol.intern("*command-line-args*"), null);
//symbol
-final public static Var CURRENT_NS = Var.intern(CLOJURE_NS, Symbol.create("*ns*"),
+final public static Var CURRENT_NS = Var.intern(CLOJURE_NS, Symbol.intern("*ns*"),
CLOJURE_NS);
-final static Var FLUSH_ON_NEWLINE = Var.intern(CLOJURE_NS, Symbol.create("*flush-on-newline*"), T);
-final static Var PRINT_META = Var.intern(CLOJURE_NS, Symbol.create("*print-meta*"), F);
-final static Var PRINT_READABLY = Var.intern(CLOJURE_NS, Symbol.create("*print-readably*"), T);
-final static Var PRINT_DUP = Var.intern(CLOJURE_NS, Symbol.create("*print-dup*"), F);
-final static Var WARN_ON_REFLECTION = Var.intern(CLOJURE_NS, Symbol.create("*warn-on-reflection*"), F);
-final static Var ALLOW_UNRESOLVED_VARS = Var.intern(CLOJURE_NS, Symbol.create("*allow-unresolved-vars*"), F);
-
-final static Var IN_NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("in-ns"), F);
-final static Var NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("ns"), F);
-static final Var PRINT_INITIALIZED = Var.intern(CLOJURE_NS, Symbol.create("print-initialized"));
-static final Var PR_ON = Var.intern(CLOJURE_NS, Symbol.create("pr-on"));
-//final static Var IMPORTS = Var.intern(CLOJURE_NS, Symbol.create("*imports*"), DEFAULT_IMPORTS);
+final static Var FLUSH_ON_NEWLINE = Var.intern(CLOJURE_NS, Symbol.intern("*flush-on-newline*"), T);
+final static Var PRINT_META = Var.intern(CLOJURE_NS, Symbol.intern("*print-meta*"), F);
+final static Var PRINT_READABLY = Var.intern(CLOJURE_NS, Symbol.intern("*print-readably*"), T);
+final static Var PRINT_DUP = Var.intern(CLOJURE_NS, Symbol.intern("*print-dup*"), F);
+final static Var WARN_ON_REFLECTION = Var.intern(CLOJURE_NS, Symbol.intern("*warn-on-reflection*"), F);
+final static Var ALLOW_UNRESOLVED_VARS = Var.intern(CLOJURE_NS, Symbol.intern("*allow-unresolved-vars*"), F);
+
+final static Var IN_NS_VAR = Var.intern(CLOJURE_NS, Symbol.intern("in-ns"), F);
+final static Var NS_VAR = Var.intern(CLOJURE_NS, Symbol.intern("ns"), F);
+static final Var PRINT_INITIALIZED = Var.intern(CLOJURE_NS, Symbol.intern("print-initialized"));
+static final Var PR_ON = Var.intern(CLOJURE_NS, Symbol.intern("pr-on"));
+//final static Var IMPORTS = Var.intern(CLOJURE_NS, Symbol.intern("*imports*"), DEFAULT_IMPORTS);
final static IFn inNamespace = new AFn(){
public Object invoke(Object arg1) throws Exception{
Symbol nsname = (Symbol) arg1;
@@ -278,12 +278,12 @@ static public void addURL(Object url) throws Exception{
static{
Keyword arglistskw = Keyword.intern(null, "arglists");
- Symbol namesym = Symbol.create("name");
- OUT.setTag(Symbol.create("java.io.Writer"));
- CURRENT_NS.setTag(Symbol.create("clojure.lang.Namespace"));
+ Symbol namesym = Symbol.intern("name");
+ OUT.setTag(Symbol.intern("java.io.Writer"));
+ CURRENT_NS.setTag(Symbol.intern("clojure.lang.Namespace"));
AGENT.setMeta(map(DOC_KEY, "The agent currently running an action on this thread, else nil"));
- AGENT.setTag(Symbol.create("clojure.lang.Agent"));
- MATH_CONTEXT.setTag(Symbol.create("java.math.MathContext"));
+ AGENT.setTag(Symbol.intern("clojure.lang.Agent"));
+ MATH_CONTEXT.setTag(Symbol.intern("java.math.MathContext"));
Var nv = Var.intern(CLOJURE_NS, NAMESPACE, bootNamespace);
nv.setMacro();
Var v;
@@ -419,8 +419,8 @@ static void doInit() throws Exception{
RT.map(CURRENT_NS, CURRENT_NS.deref(),
WARN_ON_REFLECTION, WARN_ON_REFLECTION.deref()));
try {
- Symbol USER = Symbol.create("user");
- Symbol CLOJURE = Symbol.create("clojure.core");
+ Symbol USER = Symbol.intern("user");
+ Symbol CLOJURE = Symbol.intern("clojure.core");
Var in_ns = var("clojure.core", "in-ns");
Var refer = var("clojure.core", "refer");
diff --git a/src/jvm/clojure/lang/Symbol.java b/src/jvm/clojure/lang/Symbol.java
index dbf3b36e..247f4b36 100644
--- a/src/jvm/clojure/lang/Symbol.java
+++ b/src/jvm/clojure/lang/Symbol.java
@@ -49,14 +49,6 @@ static public Symbol intern(String nsname){
return new Symbol(nsname.substring(0, i).intern(), nsname.substring(i + 1).intern());
}
-static public Symbol create(String name_interned){
- return new Symbol(null, name_interned);
-}
-
-static public Symbol create(String ns_interned, String name_interned){
- return new Symbol(ns_interned, name_interned);
-}
-
private Symbol(String ns_interned, String name_interned){
this.name = name_interned;
this.ns = ns_interned;
diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java
index 6df652b0..ca3b9533 100644
--- a/src/jvm/clojure/lang/Var.java
+++ b/src/jvm/clojure/lang/Var.java
@@ -100,10 +100,10 @@ public String toString(){
public static Var find(Symbol nsQualifiedSym){
if(nsQualifiedSym.ns == null)
throw new IllegalArgumentException("Symbol must be namespace-qualified");
- Namespace ns = Namespace.find(Symbol.create(nsQualifiedSym.ns));
+ Namespace ns = Namespace.find(Symbol.intern(nsQualifiedSym.ns));
if(ns == null)
throw new IllegalArgumentException("No such namespace: " + nsQualifiedSym.ns);
- return ns.findInternedVar(Symbol.create(nsQualifiedSym.name));
+ return ns.findInternedVar(Symbol.intern(nsQualifiedSym.name));
}
public static Var intern(Symbol nsName, Symbol sym){
diff --git a/test/clojure/test_clojure.clj b/test/clojure/test_clojure.clj
index a82ed0ae..2f3fc4f8 100644
--- a/test/clojure/test_clojure.clj
+++ b/test/clojure/test_clojure.clj
@@ -65,6 +65,7 @@
:def
:keywords
:data
+ :reflect
])
(def test-namespaces
diff --git a/test/clojure/test_clojure/data_structures.clj b/test/clojure/test_clojure/data_structures.clj
index a1f5b825..7679b2b6 100644
--- a/test/clojure/test_clojure/data_structures.clj
+++ b/test/clojure/test_clojure/data_structures.clj
@@ -112,40 +112,45 @@
;; *** Collections ***
(deftest test-count
- (are [x y] (= x y)
- (count nil) 0
-
- (count ()) 0
- (count '(1)) 1
- (count '(1 2 3)) 3
-
- (count []) 0
- (count [1]) 1
- (count [1 2 3]) 3
-
- (count #{}) 0
- (count #{1}) 1
- (count #{1 2 3}) 3
-
- (count {}) 0
- (count {:a 1}) 1
- (count {:a 1 :b 2 :c 3}) 3
-
- (count "") 0
- (count "a") 1
- (count "abc") 3
-
- (count (into-array [])) 0
- (count (into-array [1])) 1
- (count (into-array [1 2 3])) 3
-
- (count (java.util.ArrayList. [])) 0
- (count (java.util.ArrayList. [1])) 1
- (count (java.util.ArrayList. [1 2 3])) 3
-
- (count (java.util.HashMap. {})) 0
- (count (java.util.HashMap. {:a 1})) 1
- (count (java.util.HashMap. {:a 1 :b 2 :c 3})) 3 )
+ (let [EMPTY clojure.lang.PersistentQueue/EMPTY]
+ (are [x y] (= (count x) y)
+ EMPTY 0
+ (into EMPTY [:a :b]) 2
+ (-> (into EMPTY [:a :b]) pop pop) 0
+
+ nil 0
+
+ () 0
+ '(1) 1
+ '(1 2 3) 3
+
+ [] 0
+ [1] 1
+ [1 2 3] 3
+
+ #{} 0
+ #{1} 1
+ #{1 2 3} 3
+
+ {} 0
+ {:a 1} 1
+ {:a 1 :b 2 :c 3} 3
+
+ "" 0
+ "a" 1
+ "abc" 3
+
+ (into-array []) 0
+ (into-array [1]) 1
+ (into-array [1 2 3]) 3
+
+ (java.util.ArrayList. []) 0
+ (java.util.ArrayList. [1]) 1
+ (java.util.ArrayList. [1 2 3]) 3
+
+ (java.util.HashMap. {}) 0
+ (java.util.HashMap. {:a 1}) 1
+ (java.util.HashMap. {:a 1 :b 2 :c 3}) 3 ))
; different types
(are [x] (= (count [x]) 1)
diff --git a/test/clojure/test_clojure/ns_libs.clj b/test/clojure/test_clojure/ns_libs.clj
index 75d8ce1e..37afacb3 100644
--- a/test/clojure/test_clojure/ns_libs.clj
+++ b/test/clojure/test_clojure/ns_libs.clj
@@ -73,6 +73,14 @@
#"Integer already refers to: class java.lang.Integer"
(defrecord Integer [])))))
+(deftest resolution
+ (let [s (gensym)]
+ (are [result expr] (= result expr)
+ #'clojure.core/first (ns-resolve 'clojure.core 'first)
+ nil (ns-resolve 'clojure.core s)
+ nil (ns-resolve 'clojure.core {'first :local-first} 'first)
+ nil (ns-resolve 'clojure.core {'first :local-first} s))))
+
(deftest refer-error-messages
(let [temp-ns (gensym)]
(binding [*ns* *ns*]
diff --git a/test/clojure/test_clojure/reflect.clj b/test/clojure/test_clojure/reflect.clj
new file mode 100644
index 00000000..416092ac
--- /dev/null
+++ b/test/clojure/test_clojure/reflect.clj
@@ -0,0 +1,33 @@
+(ns clojure.test-clojure.reflect
+ (:use clojure.data [clojure.reflect :as reflect] clojure.test clojure.pprint)
+ (:import [clojure.reflect AsmReflector JavaReflector]))
+
+(defn nodiff
+ [x y]
+ (let [[x-only y-only common] (diff x y)]
+ (when (or x-only y-only)
+ (is false (with-out-str (pprint {:x-only x-only
+ :y-only y-only
+ :common common}))))))
+
+(deftest compare-reflect-and-asm
+ (let [cl (.getContextClassLoader (Thread/currentThread))
+ asm-reflector (AsmReflector. cl)
+ java-reflector (JavaReflector. cl)]
+ (doseq [classname '[java.lang.Runnable
+ java.lang.Object
+ java.io.FileInputStream
+ clojure.lang.Compiler
+ clojure.lang.PersistentVector]]
+ (nodiff (type-reflect classname :reflector asm-reflector)
+ (type-reflect classname :reflector java-reflector)))))
+
+(deftest field-descriptor->class-symbol-test
+ (are [s d] (= s (@#'reflect/field-descriptor->class-symbol d))
+ 'clojure.asm.Type<><> "[[Lclojure/asm/Type;"
+ 'int "I"
+ 'java.lang.Object "Ljava.lang.Object;"))
+
+(deftest internal-name->class-symbol-test
+ (are [s n] (= s (@#'reflect/internal-name->class-symbol n))
+ 'java.lang.Exception "java/lang/Exception"))